Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how would I do environment reflection in webgl without using a library like three.js?

I'm trying to figure out how to do environment mapping onto an object. Here's the setup:

teapot

How would I make the teapot's surface reflect it's surroundings? So what I mean by that is, instead of the teapot being that shade of gray, its surface should reflect its environment, so it should have the checkerboard mapped onto its surface.

This is an example of what I'm trying to accomplish, but its using Three.js and I want to do this on my own (this is for a class).

http://aerotwist.com/tutorials/create-your-own-environment-maps/demo/

Does this make sense? How would I get started?


Follow-Up

I answered this question after finishing my homework assignment: https://stackoverflow.com/a/10093646/196921. Refer to the answer for links and code :)

like image 346
Hristo Avatar asked Apr 09 '12 20:04

Hristo


2 Answers

I found a good example of this teapot here...

https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/demos/google/shiny-teapot/index.html

Looking through the source code, I found what I was looking for:

function loadCubeMap(base, suffix) {
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

    var faces = [["posx.png", gl.TEXTURE_CUBE_MAP_POSITIVE_X],
                 ["negx.png", gl.TEXTURE_CUBE_MAP_NEGATIVE_X],
                 ["posy.png", gl.TEXTURE_CUBE_MAP_POSITIVE_Y],
                 ["negy.png", gl.TEXTURE_CUBE_MAP_NEGATIVE_Y],
                 ["posz.png", gl.TEXTURE_CUBE_MAP_POSITIVE_Z],
                 ["negz.png", gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]];
    for (var i = 0; i < faces.length; i++) {
        var face = faces[i][1];
        var image = new Image();
        image.onload = function(texture, face, image) {
            return function() {
                gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
                gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
                gl.texImage2D(face, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
            }
        } (texture, face, image);
        image.src = faces[i][0];
    }
    return texture;
}

... and the example fragment shader (which has more than I need for the environment reflection mapping)...

precision mediump float;
const float bumpHeight = 0.2;

uniform sampler2D normalSampler;
uniform samplerCube envSampler;

varying vec2 texCoord;
varying vec3 worldEyeVec;
varying vec3 worldNormal;
varying vec3 worldTangent;
varying vec3 worldBinorm;

void main() {
    vec2 bump = (texture2D(normalSampler texCoord.xy).xy * 2.0 - 1.0) * bumpHeight;
    vec3 normal = normalize(worldNormal);
    vec3 tangent = normalize(worldTangent);
    vec3 binormal = normalize(worldBinorm);
    vec3 nb = normal + bump.x * tangent + bump.y * binormal;
    nb = normalize(nb);
    vec3 worldEye = normalize(worldEyeVec);
    vec3 lookup = reflect(worldEye nb);
    vec4 color = textureCube(envSampler, lookup);  // <--- this was the aha! line
    gl_FragColor = color;
}

The result came out to be kinda cool...

teapot with environment mapping

Feel free to check it out at http://hristo.oskov.com/projects/cs418/mp3/. The source code is all there in its glory... the code sucks so please don't judge me :) This is the main JS file: http://hristo.oskov.com/projects/cs418/mp3/js/mp3.js. The shaders are in the index.html page so just view source.

like image 180
Hristo Avatar answered Oct 27 '22 00:10

Hristo


The basic approach for rendering a reflective object is:

  1. Placing the camera at the center of the object, render the scene onto six textures representing the view out six faces of a cube around that object.
  2. Write a fragment shader that reflects the line of sight across the surface normal and traces out to where that intersects the cube to find the color seen in the reflection.

(I've never actually done this myself, but I've seen tutorials like this one).

like image 29
Russell Zahniser Avatar answered Oct 26 '22 22:10

Russell Zahniser