diff --git a/java/examples/Topics/Shaders/DomeProjection/CubeMapUtils.pde b/java/examples/Topics/Shaders/DomeProjection/CubeMapUtils.pde new file mode 100644 index 000000000..95a862184 --- /dev/null +++ b/java/examples/Topics/Shaders/DomeProjection/CubeMapUtils.pde @@ -0,0 +1,99 @@ +void initCubeMap() { + gridTex = loadImage("grid.png"); + sphereDetail(50); + domeSphere = createShape(SPHERE, height/2.0f); + domeSphere.setTexture(gridTex); + domeSphere.rotateX(HALF_PI); + domeSphere.setStroke(false); + + PGL pgl = beginPGL(); + + envMapTextureID = IntBuffer.allocate(1); + pgl.genTextures(1, envMapTextureID); + pgl.bindTexture(PGL.TEXTURE_CUBE_MAP, envMapTextureID.get(0)); + pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_WRAP_S, PGL.CLAMP_TO_EDGE); + pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_WRAP_T, PGL.CLAMP_TO_EDGE); + pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_WRAP_R, PGL.CLAMP_TO_EDGE); + pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_MIN_FILTER, PGL.NEAREST); + pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_MAG_FILTER, PGL.NEAREST); + for (int i = PGL.TEXTURE_CUBE_MAP_POSITIVE_X; i < PGL.TEXTURE_CUBE_MAP_POSITIVE_X + 6; i++) { + pgl.texImage2D(i, 0, PGL.RGBA8, envMapSize, envMapSize, 0, PGL.RGBA, PGL.UNSIGNED_BYTE, null); + } + + // Init fbo, rbo + fbo = IntBuffer.allocate(1); + rbo = IntBuffer.allocate(1); + pgl.genFramebuffers(1, fbo); + pgl.bindFramebuffer(PGL.FRAMEBUFFER, fbo.get(0)); + pgl.framebufferTexture2D(PGL.FRAMEBUFFER, PGL.COLOR_ATTACHMENT0, PGL.TEXTURE_CUBE_MAP_POSITIVE_X, envMapTextureID.get(0), 0); + + pgl.genRenderbuffers(1, rbo); + pgl.bindRenderbuffer(PGL.RENDERBUFFER, rbo.get(0)); + pgl.renderbufferStorage(PGL.RENDERBUFFER, PGL.DEPTH_COMPONENT24, envMapSize, envMapSize); + + // Attach depth buffer to FBO + pgl.framebufferRenderbuffer(PGL.FRAMEBUFFER, PGL.DEPTH_ATTACHMENT, PGL.RENDERBUFFER, rbo.get(0)); + + pgl.enable(PGL.TEXTURE_CUBE_MAP); + pgl.activeTexture(PGL.TEXTURE1); + pgl.bindTexture(PGL.TEXTURE_CUBE_MAP, envMapTextureID.get(0)); + + endPGL(); + + // Load cubemap shader. + cubemapShader = loadShader("cubemapfrag.glsl", "cubemapvert.glsl"); + cubemapShader.set("EnvMap", 1); +} + +void drawCubeMap() { + regenerateEnvMap(); + drawDomeMaster(); +} + +void drawDomeMaster() { + ortho(); + resetMatrix(); + shader(cubemapShader); + shape(domeSphere); + resetShader(); +} + +// Called to regenerate the envmap +void regenerateEnvMap() { + PGL pgl = beginPGL(); + + // bind fbo + pgl.bindFramebuffer(PGL.FRAMEBUFFER, fbo.get(0)); + + // generate 6 views from origin(0, 0, 0) + pgl.viewport(0, 0, envMapSize, envMapSize); + perspective(90.0f * DEG_TO_RAD, 1.0f, 1.0f, 1025.0f); + for (int face = PGL.TEXTURE_CUBE_MAP_POSITIVE_X; face < + PGL.TEXTURE_CUBE_MAP_NEGATIVE_Z; face++) { + resetMatrix(); + + if (face == PGL.TEXTURE_CUBE_MAP_POSITIVE_X) { + camera(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f); + } else if (face == PGL.TEXTURE_CUBE_MAP_NEGATIVE_X) { + camera(0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f); + } else if (face == PGL.TEXTURE_CUBE_MAP_POSITIVE_Y) { + camera(0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, -1.0f); + } else if (face == PGL.TEXTURE_CUBE_MAP_NEGATIVE_Y) { + camera(0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f); + } else if (face == PGL.TEXTURE_CUBE_MAP_POSITIVE_Z) { + camera(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f); + } + + scale(-1, 1, -1); + translate(-width * 0.5f, -height * 0.5f, -500); + + pgl.framebufferTexture2D(PGL.FRAMEBUFFER, PGL.COLOR_ATTACHMENT0, face, envMapTextureID.get(0), 0); + + drawScene(); // Draw objects in the scene + flush(); // Make sure that the geometry in the scene is pushed to the GPU + noLights(); // Disabling lights to avoid adding many times + pgl.framebufferTexture2D(PGL.FRAMEBUFFER, PGL.COLOR_ATTACHMENT0, face, 0, 0); + } + + endPGL(); +} diff --git a/java/examples/Topics/Shaders/DomeProjection/DomeProjection.pde b/java/examples/Topics/Shaders/DomeProjection/DomeProjection.pde new file mode 100644 index 000000000..6c869eab7 --- /dev/null +++ b/java/examples/Topics/Shaders/DomeProjection/DomeProjection.pde @@ -0,0 +1,52 @@ +/** + * DomeProjection + * + * This sketch uses use environmental mapping to render the output + * on a full spherical come. + * + * Based on the FullDomeTemplate code from Christopher Warnow: + * https://github.com/mphasize/FullDome + * + */ + +import java.nio.IntBuffer; + +PShader cubemapShader; +PShape domeSphere; +PImage gridTex; + +IntBuffer fbo; +IntBuffer rbo; +IntBuffer envMapTextureID; + +int envMapSize = 1024; + +void setup() { + size(640, 640, P3D); + initCubeMap(); +} + +void draw() { + background(0); + drawCubeMap(); +} + +void drawScene() { + background(0); + stroke(255, 0, 0); + strokeWeight(2); + for (int i = -width; i < 2 * width; i += 50) { + line(i, -height, -100, i, 2 *height, -100); + } + for (int i = -height; i < 2 * height; i += 50) { + line(-width, i, -100, 2 * width, i, -100); + } + + lights(); + noStroke(); + translate(mouseX, mouseY, 200); + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.01); + box(100); +} + diff --git a/java/examples/Topics/Shaders/DomeProjection/data/cubemapfrag.glsl b/java/examples/Topics/Shaders/DomeProjection/data/cubemapfrag.glsl new file mode 100644 index 000000000..9eea974a4 --- /dev/null +++ b/java/examples/Topics/Shaders/DomeProjection/data/cubemapfrag.glsl @@ -0,0 +1 @@ +uniform sampler2D texture; uniform samplerCube EnvMap; varying vec3 reflectDir; uniform vec2 texOffset; varying vec4 vertColor; varying vec4 vertTexCoord; void main() { // gl_FragColor = texture2D(texture, vertTexCoord.st) * vertColor; vec3 envColor = vec3(textureCube(EnvMap, reflectDir)); gl_FragColor = vec4(envColor, 1.0); } /* void main() { // Look up environment map value in cube map vec3 envColor = vec3(textureCube(EnvMap, ReflectDir)); gl_FragColor = vec4(envColor, 1.0); } */ \ No newline at end of file diff --git a/java/examples/Topics/Shaders/DomeProjection/data/cubemapvert.glsl b/java/examples/Topics/Shaders/DomeProjection/data/cubemapvert.glsl new file mode 100644 index 000000000..f52f94419 --- /dev/null +++ b/java/examples/Topics/Shaders/DomeProjection/data/cubemapvert.glsl @@ -0,0 +1 @@ +#define PROCESSING_TEXTURE_SHADER uniform mat4 transform; uniform mat4 modelview; uniform mat4 texMatrix; attribute vec4 vertex; attribute vec4 color; attribute vec2 texCoord; attribute vec3 normal; varying vec4 vertColor; varying vec4 vertTexCoord; uniform mat3 normalMatrix; varying vec3 reflectDir; void main() { gl_Position = transform * vertex; vec3 ecNormal = normalize(normalMatrix * normal); // Vertex in eye coordinates vec3 ecVertex = vec3(modelview * vertex); // Normal vector in eye coordinates vec3 eyeDir = ecVertex.xyz; reflectDir = reflect(eyeDir, ecNormal); vertColor = color; vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); } /* varying vec3 ReflectDir; void main() { gl_Position = ftransform(); vec3 normal = normalize(gl_NormalMatrix * gl_Normal); vec4 pos = gl_ModelViewMatrix * gl_Vertex; vec3 eyeDir = pos.xyz; ReflectDir = reflect(eyeDir, normal); } */ \ No newline at end of file