GLUSvoid GLUSAPIENTRY glusVector3Refractf(GLUSfloat result[3], const GLUSfloat incident[3], const GLUSfloat normal[3], const float eta) { // see http://www.opengl.org/sdk/docs/manglsl/xhtml/refract.xml // see http://en.wikipedia.org/wiki/Snell%27s_law // see http://www.hugi.scene.org/online/coding/hugi%2023%20-%20torefrac.htm for a and b vector. // In this implementation, the incident vector points into the interface. So the sings do change. GLUSfloat nDotI = glusVector3Dotf(normal, incident); GLUSfloat k = 1.0f - eta * eta * (1.0f - nDotI * nDotI); if (k < 0.0f) { result[0] = 0.0f; result[1] = 0.0f; result[2] = 0.0f; } else { GLUSfloat a[3]; GLUSfloat b[3]; glusVector3MultiplyScalarf(a, incident, eta); glusVector3MultiplyScalarf(b, normal, eta * nDotI + sqrtf(k)); glusVector3SubtractVector3f(result, a, b); } }
Vector3 Vector3::operator *(float scalar) const { Vector3 result; glusVector3MultiplyScalarf(result.v, v, scalar); return result; }
GLUSfloat GLUSAPIENTRY glusVector3Fresnelf(const GLUSfloat incident[3], const GLUSfloat normal[3], const GLUSfloat R0) { // see http://en.wikipedia.org/wiki/Schlick%27s_approximation GLUSfloat negIncident[3]; glusVector3MultiplyScalarf(negIncident, incident, -1.0f); return R0 + (1.0f - R0) * powf(1.0f - glusVector3Dotf(negIncident, normal), 5.0f); }
GLUSvoid GLUSAPIENTRY glusVector3Reflectf(GLUSfloat result[3], const GLUSfloat incident[3], const GLUSfloat normal[3]) { glusVector3MultiplyScalarf(result, normal, 2.0f * glusVector3Dotf(normal, incident)); glusVector3SubtractVector3f(result, incident, result); }
static GLvoid march(GLfloat pixelColor[4], const GLfloat rayPosition[4], const GLfloat rayDirection[3], const GLint depth) { GLint i, k, m, o; Primitive* primitiveNear = 0; GLfloat marchPosition[4]; GLfloat marchDirection[3]; GLfloat hitPosition[4]; GLfloat hitDirection[3]; GLfloat eyeDirection[3]; GLfloat t = 0.0f; // pixelColor[0] = 0.0f; pixelColor[1] = 0.0f; pixelColor[2] = 0.0f; pixelColor[3] = 1.0f; // for (i = 0; i < MAX_STEPS; i++) { GLfloat distance = INFINITY; GLfloat currentDistance; Primitive* closestPrimitive = 0; glusVector3MultiplyScalarf(marchDirection, rayDirection, t); glusPoint4AddVector3f(marchPosition, rayPosition, marchDirection); for (k = 0; k < NUM_SPHERES + NUM_BOXES; k++) { Primitive* currentPrimitive = &g_allPrimitives[k]; currentDistance = currentPrimitive->distanceFunction(marchPosition, currentPrimitive); if (currentDistance < distance) { distance = currentDistance; closestPrimitive = currentPrimitive; } } if (distance < EPSILON) { GLfloat samplePoints[4 * 6]; // Copy hit position ... glusPoint4Copyf(hitPosition, marchPosition); // ... and calculate normal by sampling around the hit position. for (k = 0; k < 6; k++) { samplePoints[k*4+0] = hitPosition[0]; samplePoints[k*4+1] = hitPosition[1]; samplePoints[k*4+2] = hitPosition[2]; samplePoints[k*4+3] = hitPosition[3]; samplePoints[k*4+k/2] += GAMMA * (k%2 == 0 ? 1.0f : -1.0f); } for (k = 0; k < 3; k++) { hitDirection[k] = closestPrimitive->distanceFunction(&samplePoints[k*2*4 + 0], closestPrimitive) - closestPrimitive->distanceFunction(&samplePoints[k*2*4 + 4], closestPrimitive); } glusVector3Normalizef(hitDirection); primitiveNear = closestPrimitive; break; } // If t is larger than a given distance, assume that there is the nothing. if (t > MAX_DISTANCE) { break; } t += distance; } // // No intersection, return background color / ambient light. if (!primitiveNear) { pixelColor[0] = 0.8f; pixelColor[1] = 0.8f; pixelColor[2] = 0.8f; return; } // glusVector3MultiplyScalarf(eyeDirection, rayDirection, -1.0f); // Diffuse and specular color for (i = 0; i < NUM_LIGHTS; i++) { PointLight* pointLight = &g_allLights[i]; GLboolean obstacle = GL_FALSE; GLfloat lightDirection[3]; GLfloat incidentLightDirection[3]; glusPoint4SubtractPoint4f(lightDirection, pointLight->position, hitPosition); glusVector3Normalizef(lightDirection); glusVector3MultiplyScalarf(incidentLightDirection, lightDirection, -1.0f); // Check for obstacles between current hit point surface and point light. for (k = 0; k < NUM_SPHERES + NUM_BOXES; k++) { Primitive* obstaclePrimitive = &g_allPrimitives[k]; if (obstaclePrimitive == primitiveNear) { continue; } t = 0.0f; for (m = 0; m < MAX_STEPS; m++) { GLfloat distance = INFINITY; GLfloat currentDistance; Primitive* closestPrimitive = 0; glusVector3MultiplyScalarf(marchDirection, lightDirection, -t); glusPoint4AddVector3f(marchPosition, pointLight->position, marchDirection); for (o = 0; o < NUM_SPHERES + NUM_BOXES; o++) { Primitive* currentPrimitive = &g_allPrimitives[o]; currentDistance = currentPrimitive->distanceFunction(marchPosition, currentPrimitive); if (currentDistance < distance && currentDistance >= 0.0f) { distance = currentDistance; closestPrimitive = currentPrimitive; } else if (currentDistance > distance && currentDistance < 0.0f) { distance = currentDistance; closestPrimitive = currentPrimitive; } } if (distance < EPSILON) { if (closestPrimitive != primitiveNear) { obstacle = GL_TRUE; } break; } if (t > MAX_DISTANCE) { break; } t += distance; } } // If no obstacle, illuminate hit point surface. if (!obstacle) { GLfloat diffuseIntensity = glusMathMaxf(0.0f, glusVector3Dotf(hitDirection, lightDirection)); if (diffuseIntensity > 0.0f) { GLfloat specularReflection[3]; GLfloat eDotR; pixelColor[0] = pixelColor[0] + diffuseIntensity * primitiveNear->material.diffuseColor[0] * pointLight->color[0]; pixelColor[1] = pixelColor[1] + diffuseIntensity * primitiveNear->material.diffuseColor[1] * pointLight->color[1]; pixelColor[2] = pixelColor[2] + diffuseIntensity * primitiveNear->material.diffuseColor[2] * pointLight->color[2]; glusVector3Reflectf(specularReflection, incidentLightDirection, hitDirection); glusVector3Normalizef(specularReflection); eDotR = glusMathMaxf(0.0f, glusVector3Dotf(eyeDirection, specularReflection)); if (eDotR > 0.0f) { GLfloat specularIntensity = powf(eDotR, primitiveNear->material.shininess); pixelColor[0] = pixelColor[0] + specularIntensity * primitiveNear->material.specularColor[0] * pointLight->color[0]; pixelColor[1] = pixelColor[1] + specularIntensity * primitiveNear->material.specularColor[1] * pointLight->color[1]; pixelColor[2] = pixelColor[2] + specularIntensity * primitiveNear->material.specularColor[2] * pointLight->color[2]; } } } } // Emissive color pixelColor[0] = pixelColor[0] + primitiveNear->material.emissiveColor[0]; pixelColor[1] = pixelColor[1] + primitiveNear->material.emissiveColor[1]; pixelColor[2] = pixelColor[2] + primitiveNear->material.emissiveColor[2]; }
static GLvoid trace(GLfloat pixelColor[4], const GLfloat rayPosition[4], const GLfloat rayDirection[3], const GLint depth) { const GLfloat bias = 1e-4f; GLint i, k; GLfloat tNear = INFINITY; Sphere* sphereNear = 0; GLboolean insideSphereNear = GL_FALSE; GLfloat ray[3]; GLfloat hitPosition[4]; GLfloat hitDirection[3]; GLfloat biasedPositiveHitPosition[4]; GLfloat biasedNegativeHitPosition[4]; GLfloat biasedHitDirection[3]; GLfloat eyeDirection[3]; // pixelColor[0] = 0.0f; pixelColor[1] = 0.0f; pixelColor[2] = 0.0f; pixelColor[3] = 1.0f; // for (i = 0; i < NUM_SPHERES; i++) { GLfloat t0 = INFINITY; GLfloat t1 = INFINITY; GLboolean insideSphere = GL_FALSE; Sphere* currentSphere = &g_allSpheres[i]; GLint numberIntersections = glusIntersectRaySpheref(&t0, &t1, &insideSphere, rayPosition, rayDirection, currentSphere->center, currentSphere->radius); if (numberIntersections) { // If intersection happened inside the sphere, take second intersection point, as this one is on the surface. if (insideSphere) { t0 = t1; } // Found a sphere, which is closer. if (t0 < tNear) { tNear = t0; sphereNear = currentSphere; insideSphereNear = insideSphere; } } } // // No intersection, return background color / ambient light. if (!sphereNear) { pixelColor[0] = 0.8f; pixelColor[1] = 0.8f; pixelColor[2] = 0.8f; return; } // Calculate ray hit position ... glusVector3MultiplyScalarf(ray, rayDirection, tNear); glusPoint4AddVector3f(hitPosition, rayPosition, ray); // ... and normal glusPoint4SubtractPoint4f(hitDirection, hitPosition, sphereNear->center); glusVector3Normalizef(hitDirection); // If inside the sphere, reverse hit vector, as ray comes from inside. if (insideSphereNear) { glusVector3MultiplyScalarf(hitDirection, hitDirection, -1.0f); } // // Biasing, to avoid artifacts. glusVector3MultiplyScalarf(biasedHitDirection, hitDirection, bias); glusPoint4AddVector3f(biasedPositiveHitPosition, hitPosition, biasedHitDirection); glusPoint4SubtractVector3f(biasedNegativeHitPosition, hitPosition, biasedHitDirection); // GLfloat reflectionColor[4] = {0.0f, 0.0f, 0.0f, 1.0f}; GLfloat refractionColor[4] = {0.0f, 0.0f, 0.0f, 1.0f}; GLfloat fresnel = glusVector3Fresnelf(rayDirection, hitDirection, R0); // Reflection ... if (sphereNear->material.reflectivity > 0.0f && depth < MAX_RAY_DEPTH) { GLfloat reflectionDirection[3]; glusVector3Reflectf(reflectionDirection, rayDirection, hitDirection); glusVector3Normalizef(reflectionDirection); trace(reflectionColor, biasedPositiveHitPosition, reflectionDirection, depth + 1); } // ... refraction. if (sphereNear->material.alpha < 1.0f && depth < MAX_RAY_DEPTH) { GLfloat refractionDirection[3]; // If inside, it is from glass to air. GLfloat eta = insideSphereNear ? 1.0f / Eta : Eta; glusVector3Refractf(refractionDirection, rayDirection, hitDirection, eta); glusVector3Normalizef(refractionDirection); trace(refractionColor, biasedNegativeHitPosition, refractionDirection, depth + 1); } else { fresnel = 1.0f; } // glusVector3MultiplyScalarf(eyeDirection, rayDirection, -1.0f); // Diffuse and specular color for (i = 0; i < NUM_LIGHTS; i++) { PointLight* pointLight = &g_allLights[i]; GLboolean obstacle = GL_FALSE; GLfloat lightDirection[3]; GLfloat incidentLightDirection[3]; glusPoint4SubtractPoint4f(lightDirection, pointLight->position, hitPosition); glusVector3Normalizef(lightDirection); glusVector3MultiplyScalarf(incidentLightDirection, lightDirection, -1.0f); // Check for obstacles between current hit point surface and point light. for (k = 0; k < NUM_SPHERES; k++) { Sphere* obstacleSphere = &g_allSpheres[k]; if (obstacleSphere == sphereNear) { continue; } if (glusIntersectRaySpheref(0, 0, 0, biasedPositiveHitPosition, lightDirection, obstacleSphere->center, obstacleSphere->radius)) { obstacle = GL_TRUE; break; } } // If no obstacle, illuminate hit point surface. if (!obstacle) { GLfloat diffuseIntensity = glusMaxf(0.0f, glusVector3Dotf(hitDirection, lightDirection)); if (diffuseIntensity > 0.0f) { GLfloat specularReflection[3]; GLfloat eDotR; pixelColor[0] = pixelColor[0] + diffuseIntensity * sphereNear->material.diffuseColor[0] * pointLight->color[0]; pixelColor[1] = pixelColor[1] + diffuseIntensity * sphereNear->material.diffuseColor[1] * pointLight->color[1]; pixelColor[2] = pixelColor[2] + diffuseIntensity * sphereNear->material.diffuseColor[2] * pointLight->color[2]; glusVector3Reflectf(specularReflection, incidentLightDirection, hitDirection); glusVector3Normalizef(specularReflection); eDotR = glusMaxf(0.0f, glusVector3Dotf(eyeDirection, specularReflection)); if (eDotR > 0.0f && !insideSphereNear) { GLfloat specularIntensity = powf(eDotR, sphereNear->material.shininess); pixelColor[0] = pixelColor[0] + specularIntensity * sphereNear->material.specularColor[0] * pointLight->color[0]; pixelColor[1] = pixelColor[1] + specularIntensity * sphereNear->material.specularColor[1] * pointLight->color[1]; pixelColor[2] = pixelColor[2] + specularIntensity * sphereNear->material.specularColor[2] * pointLight->color[2]; } } } } // Emissive color pixelColor[0] = pixelColor[0] + sphereNear->material.emissiveColor[0]; pixelColor[1] = pixelColor[1] + sphereNear->material.emissiveColor[1]; pixelColor[2] = pixelColor[2] + sphereNear->material.emissiveColor[2]; // Final color with reflection and refraction pixelColor[0] = (1.0f - fresnel) * refractionColor[0] * (1.0f - sphereNear->material.alpha) + pixelColor[0] * (1.0f - sphereNear->material.reflectivity) * sphereNear->material.alpha + fresnel * reflectionColor[0] * sphereNear->material.reflectivity; pixelColor[1] = (1.0f - fresnel) * refractionColor[1] * (1.0f - sphereNear->material.alpha) + pixelColor[1] * (1.0f - sphereNear->material.reflectivity) * sphereNear->material.alpha + fresnel * reflectionColor[1] * sphereNear->material.reflectivity; pixelColor[2] = (1.0f - fresnel) * refractionColor[2] * (1.0f - sphereNear->material.alpha) + pixelColor[2] * (1.0f - sphereNear->material.reflectivity) * sphereNear->material.alpha + fresnel * reflectionColor[2] * sphereNear->material.reflectivity; }
GLUSboolean init(GLUSvoid) { GLUStextfile vertexSource; GLUStextfile fragmentSource; GLUStgaimage image; GLUSshape plane; GLint i; // glusLookAtf(g_viewMatrix, g_camera.eye[0], g_camera.eye[1], g_camera.eye[2], g_camera.center[0], g_camera.center[1], g_camera.center[2], g_camera.up[0], g_camera.up[1], g_camera.up[2]); // if (!initWavefront(g_viewMatrix, &g_light)) { return GLUS_FALSE; } // glusLoadTextFile("../Example28/shader/texture.vert.glsl", &vertexSource); glusLoadTextFile("../Example28/shader/texture.frag.glsl", &fragmentSource); glusBuildProgramFromSource(&g_program, (const GLUSchar**)&vertexSource.text, 0, 0, 0, (const GLUSchar**)&fragmentSource.text); glusDestroyTextFile(&vertexSource); glusDestroyTextFile(&fragmentSource); // // Retrieve the uniform locations in the program. g_viewProjectionMatrixLocation = glGetUniformLocation(g_program.program, "u_viewProjectionMatrix"); g_modelMatrixLocation = glGetUniformLocation(g_program.program, "u_modelMatrix"); g_normalMatrixLocation = glGetUniformLocation(g_program.program, "u_normalMatrix"); g_lightDirectionLocation = glGetUniformLocation(g_program.program, "u_lightDirection"); g_repeatLocation = glGetUniformLocation(g_program.program, "u_repeat"); g_textureLocation = glGetUniformLocation(g_program.program, "u_texture"); // Retrieve the attribute locations in the program. g_vertexLocation = glGetAttribLocation(g_program.program, "a_vertex"); g_normalLocation = glGetAttribLocation(g_program.program, "a_normal"); g_texCoordLocation = glGetAttribLocation(g_program.program, "a_texCoord"); // // SSAO shader etc. // glusLoadTextFile("../Example28/shader/ssao.vert.glsl", &vertexSource); glusLoadTextFile("../Example28/shader/ssao.frag.glsl", &fragmentSource); glusBuildProgramFromSource(&g_ssaoProgram, (const GLUSchar**)&vertexSource.text, 0, 0, 0, (const GLUSchar**)&fragmentSource.text); glusDestroyTextFile(&vertexSource); glusDestroyTextFile(&fragmentSource); // // Retrieve the uniform locations in the program. g_ssaoTextureLocation = glGetUniformLocation(g_ssaoProgram.program, "u_texture"); g_ssaoNormalTextureLocation = glGetUniformLocation(g_ssaoProgram.program, "u_normalTexture"); g_ssaoDepthTextureLocation = glGetUniformLocation(g_ssaoProgram.program, "u_depthTexture"); g_ssaoKernelLocation = glGetUniformLocation(g_ssaoProgram.program, "u_kernel"); g_ssaoRotationNoiseTextureLocation = glGetUniformLocation(g_ssaoProgram.program, "u_rotationNoiseTexture"); g_ssaoRotationNoiseScaleLocation = glGetUniformLocation(g_ssaoProgram.program, "u_rotationNoiseScale"); g_ssaoInverseProjectionMatrixLocation = glGetUniformLocation(g_ssaoProgram.program, "u_inverseProjectionMatrix"); g_ssaoProjectionMatrixLocation = glGetUniformLocation(g_ssaoProgram.program, "u_projectionMatrix"); g_ssaoRadiusLocation = glGetUniformLocation(g_ssaoProgram.program, "u_radius"); // Retrieve the attribute locations in the program. g_ssaoVertexLocation = glGetAttribLocation(g_ssaoProgram.program, "a_vertex"); g_ssaoTexCoordLocation = glGetAttribLocation(g_ssaoProgram.program, "a_texCoord"); // // Blur shader etc. // glusLoadTextFile("../Example28/shader/blur.vert.glsl", &vertexSource); glusLoadTextFile("../Example28/shader/blur.frag.glsl", &fragmentSource); glusBuildProgramFromSource(&g_blurProgram, (const GLUSchar**)&vertexSource.text, 0, 0, 0, (const GLUSchar**)&fragmentSource.text); glusDestroyTextFile(&vertexSource); glusDestroyTextFile(&fragmentSource); // // Retrieve the uniform locations in the program. g_blurColorTextureLocation = glGetUniformLocation(g_blurProgram.program, "u_colorTexture"); g_blurSSAOTextureLocation = glGetUniformLocation(g_blurProgram.program, "u_ssaoTexture"); g_blurTexelStepLocation = glGetUniformLocation(g_blurProgram.program, "u_texelStep"); g_blurNoSSAOLocation = glGetUniformLocation(g_blurProgram.program, "u_noSSAO"); // Retrieve the attribute locations in the program. g_blurVertexLocation = glGetAttribLocation(g_blurProgram.program, "a_vertex"); g_blurTexCoordLocation = glGetAttribLocation(g_blurProgram.program, "a_texCoord"); // // Texture set up for the ground plane. // glusLoadTgaImage("wood_texture.tga", &image); glGenTextures(1, &g_texture); glBindTexture(GL_TEXTURE_2D, g_texture); glTexImage2D(GL_TEXTURE_2D, 0, image.format, image.width, image.height, 0, image.format, GL_UNSIGNED_BYTE, image.data); // Mipmap generation is now included in OpenGL 3 and above glGenerateMipmap(GL_TEXTURE_2D); // Trilinear filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, 0); // // Setting up the SSAO frame buffer. // glGenTextures(1, &g_ssaoTexture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, g_ssaoTexture); glTexImage2D(GL_TEXTURE_2D, 0, GLUS_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GLUS_RGB, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); // glGenTextures(1, &g_ssaoNormalTexture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, g_ssaoNormalTexture); glTexImage2D(GL_TEXTURE_2D, 0, GLUS_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GLUS_RGB, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); // glGenTextures(1, &g_ssaoDepthTexture); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, g_ssaoDepthTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); // glGenFramebuffers(1, &g_ssaoFBO); glBindFramebuffer(GL_FRAMEBUFFER, g_ssaoFBO); // Attach the color buffer ... glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_ssaoTexture, 0); // Attach the normal buffer ... glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, g_ssaoNormalTexture, 0); // ... and the depth buffer, glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, g_ssaoDepthTexture, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { printf("GL_FRAMEBUFFER_COMPLETE error 0x%x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); return GLUS_FALSE; } glBindFramebuffer(GL_FRAMEBUFFER, 0); // // Setting up the blur frame buffer // glGenTextures(1, &g_blurTexture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, g_blurTexture); glTexImage2D(GL_TEXTURE_2D, 0, GLUS_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GLUS_RGB, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); // glGenFramebuffers(1, &g_blurFBO); glBindFramebuffer(GL_FRAMEBUFFER, g_blurFBO); // Attach the color buffer ... glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_blurTexture, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { printf("GL_FRAMEBUFFER_COMPLETE error 0x%x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); return GLUS_FALSE; } glBindFramebuffer(GL_FRAMEBUFFER, 0); // // Ground plane setup. // glusCreatePlanef(&plane, 20.0f); g_numberIndicesPlane = plane.numberIndices; glGenBuffers(1, &g_verticesVBO); glBindBuffer(GL_ARRAY_BUFFER, g_verticesVBO); glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 4 * sizeof(GLfloat), (GLfloat*)plane.vertices, GL_STATIC_DRAW); glGenBuffers(1, &g_normalsVBO); glBindBuffer(GL_ARRAY_BUFFER, g_normalsVBO); glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 3 * sizeof(GLfloat), (GLfloat*)plane.normals, GL_STATIC_DRAW); glGenBuffers(1, &g_texCoordsVBO); glBindBuffer(GL_ARRAY_BUFFER, g_texCoordsVBO); glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 2 * sizeof(GLfloat), (GLfloat*)plane.texCoords, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenBuffers(1, &g_indicesVBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesVBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, plane.numberIndices * sizeof(GLuint), (GLuint*)plane.indices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glusDestroyShapef(&plane); // glUseProgram(g_program.program); glGenVertexArrays(1, &g_vao); glBindVertexArray(g_vao); glBindBuffer(GL_ARRAY_BUFFER, g_verticesVBO); glVertexAttribPointer(g_vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_vertexLocation); glBindBuffer(GL_ARRAY_BUFFER, g_normalsVBO); glVertexAttribPointer(g_normalLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_normalLocation); glBindBuffer(GL_ARRAY_BUFFER, g_texCoordsVBO); glVertexAttribPointer(g_texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_texCoordLocation); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesVBO); glBindVertexArray(0); // glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, g_texture); glUniform1i(g_textureLocation, 0); // How many times the surface texture is repeated. glUniform1f(g_repeatLocation, 6.0f); // // Post process plane setup. // glusCreatePlanef(&plane, 1.0f); g_numberIndicesPostprocessPlane = plane.numberIndices; glGenBuffers(1, &g_postprocessVerticesVBO); glBindBuffer(GL_ARRAY_BUFFER, g_postprocessVerticesVBO); glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 4 * sizeof(GLfloat), (GLfloat*)plane.vertices, GL_STATIC_DRAW); glGenBuffers(1, &g_postprocessTexCoordsVBO); glBindBuffer(GL_ARRAY_BUFFER, g_postprocessTexCoordsVBO); glBufferData(GL_ARRAY_BUFFER, plane.numberVertices * 2 * sizeof(GLfloat), (GLfloat*)plane.texCoords, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenBuffers(1, &g_postprocessIndicesVBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_postprocessIndicesVBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, plane.numberIndices * sizeof(GLuint), (GLuint*)plane.indices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glusDestroyShapef(&plane); // glUseProgram(g_ssaoProgram.program); glGenVertexArrays(1, &g_ssaoVAO); glBindVertexArray(g_ssaoVAO); glBindBuffer(GL_ARRAY_BUFFER, g_postprocessVerticesVBO); glVertexAttribPointer(g_ssaoVertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_ssaoVertexLocation); glBindBuffer(GL_ARRAY_BUFFER, g_postprocessTexCoordsVBO); glVertexAttribPointer(g_ssaoTexCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_ssaoTexCoordLocation); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_postprocessIndicesVBO); glBindVertexArray(0); // glUniform1i(g_ssaoTextureLocation, 0); glUniform1i(g_ssaoNormalTextureLocation, 1); glUniform1i(g_ssaoDepthTextureLocation, 2); glUniform1i(g_ssaoRotationNoiseTextureLocation, 3); glUniform1f(g_ssaoRadiusLocation, SSAO_RADIUS); // // Create the Kernel for SSAO. // for (i = 0; i < KERNEL_SIZE; i++) { g_kernel[i * 3 + 0] = glusRandomUniformGetFloatf(-1.0f, 1.0f); g_kernel[i * 3 + 1] = glusRandomUniformGetFloatf(-1.0f, 1.0f); g_kernel[i * 3 + 2] = glusRandomUniformGetFloatf(0.0f, 1.0f); // Kernel hemisphere points to positive Z-Axis. glusVector3Normalizef(&g_kernel[i * 3]); // Normalize, so included in the hemisphere. GLfloat scale = (GLfloat)i / (GLfloat)KERNEL_SIZE; // Create a scale value between [0;1[ . scale = glusClampf(scale * scale, 0.1f, 1.0f); // Adjust scale, that there are more values closer to the center of the g_kernel. glusVector3MultiplyScalarf(&g_kernel[i * 3], &g_kernel[i * 3], scale); } // Pass g_kernel to shader glUniform3fv(g_ssaoKernelLocation, KERNEL_SIZE, g_kernel); // // Create the rotation noise texture // for (i = 0; i < ROTATION_NOISE_SIZE; i++) { g_rotationNoise[i * 3 + 0] = glusRandomUniformGetFloatf(-1.0f, 1.0f); g_rotationNoise[i * 3 + 1] = glusRandomUniformGetFloatf(-1.0f, 1.0f); g_rotationNoise[i * 3 + 2] = 0.0f; // Rotate on x-y-plane, so z is zero. glusVector3Normalizef(&g_rotationNoise[i * 3]); // Normalized rotation vector. } // glGenTextures(1, &g_ssaoRotationNoiseTexture); glBindTexture(GL_TEXTURE_2D, g_ssaoRotationNoiseTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, ROTATION_NOISE_SIDE_LENGTH, ROTATION_NOISE_SIDE_LENGTH, 0, GL_RGB, GL_FLOAT, g_rotationNoise); // No filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, 0); // // g_rotationNoiseScale[0] = (GLfloat)TEXTURE_WIDTH / (GLfloat)ROTATION_NOISE_SIDE_LENGTH; g_rotationNoiseScale[1] = (GLfloat)TEXTURE_HEIGHT / (GLfloat)ROTATION_NOISE_SIDE_LENGTH; // Pass the scale, as the rotation noise texture is repeated over the screen x / y times. glUniform2fv(g_ssaoRotationNoiseScaleLocation, 1, g_rotationNoiseScale); // // glUseProgram(g_blurProgram.program); glGenVertexArrays(1, &g_blurVAO); glBindVertexArray(g_blurVAO); glBindBuffer(GL_ARRAY_BUFFER, g_postprocessVerticesVBO); glVertexAttribPointer(g_blurVertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_blurVertexLocation); glBindBuffer(GL_ARRAY_BUFFER, g_postprocessTexCoordsVBO); glVertexAttribPointer(g_blurTexCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_blurTexCoordLocation); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_postprocessIndicesVBO); glBindVertexArray(0); // glUniform1i(g_blurColorTextureLocation, 0); glUniform1i(g_blurSSAOTextureLocation, 1); g_texelStep[0] = 1.0f / (GLfloat)TEXTURE_WIDTH; g_texelStep[1] = 1.0f / (GLfloat)TEXTURE_HEIGHT; // Pass the value to step from one to another texel. glUniform2fv(g_blurTexelStepLocation, 1, g_texelStep); // Variable to toggle between SSAO on and off glUniform1f(g_blurNoSSAOLocation, 0.0f); // // Basic OpenGL set up. // glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); return GLUS_TRUE; }