int main(int argc, char* argv[]) { GLUSchar* output; GLUSchar* extension; GLUSchar fileType[MAX_FILETYPE_LENGTH]; GLUSchar buffer[MAX_FILENAME_LENGTH]; GLUSint roughnessSamples; GLUSuint exponent; GLUSuint samples; GLUSint i, k, m, o, p, q, x, y, ouputLength; GLUSboolean isHDR = GLUS_FALSE; GLUStgaimage tgaOutput[2]; GLUShdrimage hdrOutput[2]; GLUSint length; GLUSint lengthExponent; GLUSint stride; GLUSfloat offset, step, roughness; GLUSfloat startVector[3] = { 1.0f, -1.0f, -1.0f }; GLUSfloat offsetVector[3]; GLUSfloat normalVector[3]; GLUSfloat* scanVectors; GLUSfloat* colorBufferLambert; GLUSfloat* colorBufferCookTorrance; GLUSfloat matrix[9]; GLUStextfile computeSource; GLUSshaderprogram computeProgram; GLUSuint localSize = 16; GLUSuint textureLambert; GLUSuint textureCookTorrance; GLUSuint scanVectorsSSBO; GLUSint mLocation; GLUSint samplesLocation; GLUSint binaryFractionFactorLocation; GLUSint roughnessLocation; if (argc != 11) { printf("Usage: Panorama2CubeMap.exe [Pos X] [Neg X] [Pos Y] [Neg Y] [Pos Z] [Neg Z] [Output] [Roughness] [Samples 2^m] [Length 2^n]\n"); return -1; } // output = argv[7]; ouputLength = strlen(output); if (ouputLength >= MAX_FILENAME_LENGTH - (MAX_FILETYPE_LENGTH - 1) - SIDE_NAMING_LENGTH - ROUGHNESS_NAMING_LENGTH - TYPE_NAMING_LENGTH) { printf("Error: Output filename too long.\n"); return -1; } roughnessSamples = atoi(argv[8]); if (roughnessSamples < 2 || roughnessSamples >= 100) { printf("Error: Invalid roughness value.\n"); return -1; } exponent = (GLUSuint)atoi(argv[9]); if (exponent > 16) { printf("Error: Invalid samples value.\n"); return -1; } samples = 1 << exponent; lengthExponent = (GLUSuint)atoi(argv[10]); if (lengthExponent > 16) { printf("Error: Invalid length value.\n"); return -1; } length = 1 << lengthExponent; if (roughnessSamples < 2 || roughnessSamples >= 100) { printf("Error: Invalid roughness value.\n"); return -1; } // extension = strrchr(argv[1], '.'); if (extension == 0) { printf("Error: No file type found.\n"); return -1; } if (strlen(extension) != MAX_FILETYPE_LENGTH - 1) { printf("Error: Invalid file type.\n"); return -1; } // Copy includes NULL terminating character. for (i = 0; i < MAX_FILETYPE_LENGTH ; i++) { fileType[i] = tolower(extension[i]); } stride = 1; printf("Loading texture cube maps ... "); if (strcmp(fileType, ".tga") == 0) { // for (i = 0; i < 6; i++) { if (!glusLoadTgaImage(argv[1 + i], &g_tgaimage[i])) { printf("failed! TGA image could not be loaded.\n"); freeTgaImages(i); return -1; } if (i > 0) { if (g_tgaimage[0].width != g_tgaimage[i].width || g_tgaimage[0].height != g_tgaimage[i].height) { printf("failed! TGA images do have different dimension.\n"); freeTgaImages(i + 1); return -1; } } else { if (g_tgaimage[0].width != g_tgaimage[i].height) { printf("failed! TGA images do have different dimension.\n"); freeTgaImages(1); return -1; } } } if (g_tgaimage[0].format == GLUS_RGB) { stride = 3; } else if (g_tgaimage[0].format == GLUS_RGBA) { stride = 4; } // tgaOutput[0] = g_tgaimage[0]; tgaOutput[0].width = length; tgaOutput[0].height = length; tgaOutput[0].data = (GLUSubyte*)malloc(length * length * stride * sizeof(GLUSubyte)); if (!tgaOutput[0].data) { printf("failed! TGA output image could not be created.\n"); freeTgaImages(6); return -1; } tgaOutput[1] = g_tgaimage[0]; tgaOutput[1].width = length; tgaOutput[1].height = length; tgaOutput[1].data = (GLUSubyte*)malloc(length * length * stride * sizeof(GLUSubyte)); if (!tgaOutput[1].data) { printf("failed! TGA output image could not be created.\n"); freeTgaImages(6); glusDestroyTgaImage(&tgaOutput[0]); return -1; } } else if (strcmp(fileType, ".hdr") == 0) { isHDR = GLUS_TRUE; for (i = 0; i < 6; i++) { if (!glusLoadHdrImage(argv[1 + i], &g_hdrimage[i])) { printf("failed! HDR image could not be loaded.\n"); freeHdrImages(i); return -1; } if (i > 0) { if (g_hdrimage[0].width != g_hdrimage[i].width || g_hdrimage[0].height != g_hdrimage[i].height) { printf("failed! HDR images do have different dimension.\n"); freeHdrImages(i + 1); return -1; } } else { if (g_hdrimage[0].width != g_hdrimage[i].height) { printf("failed! HDR images do have different dimension.\n"); freeHdrImages(1); return -1; } } } stride = 3; // hdrOutput[0] = g_hdrimage[0]; hdrOutput[0].width = length; hdrOutput[0].height = length; hdrOutput[0].data = (GLUSfloat*)malloc(length * length * stride * sizeof(GLUSfloat)); if (!hdrOutput[0].data) { printf("failed! HDR output image could not be created.\n"); freeHdrImages(6); return -1; } hdrOutput[1] = g_hdrimage[0]; hdrOutput[1].width = length; hdrOutput[1].height = length; hdrOutput[1].data = (GLUSfloat*)malloc(length * length * stride * sizeof(GLUSfloat)); if (!hdrOutput[1].data) { printf("failed! HDR output image could not be created.\n"); freeHdrImages(6); glusDestroyHdrImage(&hdrOutput[1]); return -1; } } else { printf("failed. Unknown file type.\n"); return -1; } printf("completed!\n"); // Contains the vectors to scan and generate one side of the pre-filtered cube map. scanVectors = (GLUSfloat*)malloc(length * length * (3 + 1) * sizeof(GLUSfloat)); if (!scanVectors) { printf("Error: Scan scanVectors could not be created.\n"); freeHdrImages(6); return -1; } // Color buffer needed to gather the pixels from the texture. colorBufferLambert = (GLUSfloat*)malloc(length * length * 4 * sizeof(GLUSfloat)); if (!colorBufferLambert) { printf("Error: Color buffer could not be created.\n"); freeHdrImages(6); free(scanVectors); return -1; } // Color buffer needed to gather the pixels from the texture. colorBufferCookTorrance = (GLUSfloat*)malloc(length * length * 4 * sizeof(GLUSfloat)); if (!colorBufferCookTorrance) { printf("Error: Color buffer could not be created.\n"); freeHdrImages(6); free(scanVectors); free(colorBufferLambert); return -1; } // // Initialize OpenGL, as it is needed for the compute shader. // glusPrepareContext(4, 3, GLUS_FORWARD_COMPATIBLE_BIT); if (!glusCreateWindow("GLUS Example Window", 512, 512, 0, 0, GLUS_FALSE)) { printf("Could not create window!\n"); return -1; } if (!glusStartup()) { return -1; } // // Compute shader for pre-filtering. // glusLoadTextFile("../PreFilterCubeMap/shader/prefilter.comp.glsl", &computeSource); glusBuildComputeProgramFromSource(&computeProgram, (const GLchar**)&computeSource.text); glusDestroyTextFile(&computeSource); // mLocation = glGetUniformLocation(computeProgram.program, "u_m"); samplesLocation = glGetUniformLocation(computeProgram.program, "u_samples"); binaryFractionFactorLocation = glGetUniformLocation(computeProgram.program, "u_binaryFractionFactor"); roughnessLocation = glGetUniformLocation(computeProgram.program, "u_roughness"); // glUseProgram(computeProgram.program); // // // // Create cube maps if (isHDR) { createHdrCubeMap(); freeHdrImages(6); } else { createTgaCubeMap(); freeTgaImages(6); } // Prepare texture, where the pre-filtered image is stored: Lambert glGenTextures(1, &textureLambert); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureLambert); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, length, length, 0, GL_RGBA, GL_FLOAT, 0); 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_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // see binding = 1 in the shader glBindImageTexture(1, textureLambert, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); glPixelStorei(GL_PACK_ALIGNMENT, 1); // // Prepare texture, where the pre-filtered image is stored: Cook-Torrance glGenTextures(1, &textureCookTorrance); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureCookTorrance); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, length, length, 0, GL_RGBA, GL_FLOAT, 0); 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_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // see binding = 2 in the shader glBindImageTexture(2, textureCookTorrance, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); glPixelStorei(GL_PACK_ALIGNMENT, 1); // // // step = 2.0f / (GLUSfloat)length; offset = step * 0.5f; // Prepare save name. strcpy(buffer, output); buffer[ouputLength + 0] = '_'; buffer[ouputLength + 4] = '_'; buffer[ouputLength + 6] = '_'; buffer[ouputLength + 9] = '_'; for (i = ouputLength + SIDE_NAMING_LENGTH + ROUGHNESS_NAMING_LENGTH + TYPE_NAMING_LENGTH; i < ouputLength + SIDE_NAMING_LENGTH + ROUGHNESS_NAMING_LENGTH + TYPE_NAMING_LENGTH + MAX_FILETYPE_LENGTH; i++) { buffer[i] = fileType[i - (ouputLength + SIDE_NAMING_LENGTH + ROUGHNESS_NAMING_LENGTH + TYPE_NAMING_LENGTH)]; } // // Setup scan vectors buffer for compute shader. glGenBuffers(1, &scanVectorsSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, scanVectorsSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, length * length * (3 + 1) * sizeof(GLfloat), 0, GL_DYNAMIC_DRAW); // see binding = 3 in the shader glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, scanVectorsSSBO); // Setup m and samples for compute shader. glUniform1ui(mLocation, exponent); glUniform1ui(samplesLocation, samples); // Results are in range [0.0 1.0] and not [0.0, 1.0[. glUniform1f(binaryFractionFactorLocation, 1.0f / (powf(2.0f, (GLfloat)exponent) - 1.0f)); printf("Generating pre filtered cube maps ...\n"); for (i = 0; i < 6; i++) { printf("Side: %d\n", i); switch (i) { case 0: // Positive X glusMatrix3x3Identityf(matrix); buffer[ouputLength + 1] = 'P'; buffer[ouputLength + 2] = 'O'; buffer[ouputLength + 3] = 'S'; buffer[ouputLength + 5] = 'X'; break; case 1: // Negative X glusMatrix3x3Identityf(matrix); glusMatrix3x3RotateRyf(matrix, 180.0f); buffer[ouputLength + 1] = 'N'; buffer[ouputLength + 2] = 'E'; buffer[ouputLength + 3] = 'G'; buffer[ouputLength + 5] = 'X'; break; case 2: // Positive Y glusMatrix3x3Identityf(matrix); glusMatrix3x3RotateRxf(matrix, 90.0f); glusMatrix3x3RotateRyf(matrix, 90.0f); buffer[ouputLength + 1] = 'P'; buffer[ouputLength + 2] = 'O'; buffer[ouputLength + 3] = 'S'; buffer[ouputLength + 5] = 'Y'; break; case 3: // Negative Y glusMatrix3x3Identityf(matrix); glusMatrix3x3RotateRxf(matrix, -90.0f); glusMatrix3x3RotateRyf(matrix, 90.0f); buffer[ouputLength + 1] = 'N'; buffer[ouputLength + 2] = 'E'; buffer[ouputLength + 3] = 'G'; buffer[ouputLength + 5] = 'Y'; break; case 4: // Positive Z glusMatrix3x3Identityf(matrix); glusMatrix3x3RotateRyf(matrix, -90.0f); buffer[ouputLength + 1] = 'P'; buffer[ouputLength + 2] = 'O'; buffer[ouputLength + 3] = 'S'; buffer[ouputLength + 5] = 'Z'; break; case 5: // Negative Z glusMatrix3x3Identityf(matrix); glusMatrix3x3RotateRyf(matrix, 90.0f); buffer[ouputLength + 1] = 'N'; buffer[ouputLength + 2] = 'E'; buffer[ouputLength + 3] = 'G'; buffer[ouputLength + 5] = 'Z'; break; } // Generate scan vectors for (k = 0; k < length; k++) { for (m = 0; m < length; m++) { offsetVector[0] = 0.0f; offsetVector[1] = offset + step * (GLUSfloat)k; offsetVector[2] = offset + step * (GLUSfloat)m; glusVector3AddVector3f(normalVector, startVector, offsetVector); glusVector3Normalizef(normalVector); glusMatrix3x3MultiplyVector3f(&scanVectors[k * length * (3 + 1) + m * (3 + 1)], matrix, normalVector); } } // Upload scan vectors for each side. glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, length * length * (3 + 1) * sizeof(GLfloat), scanVectors); // For all roughness levels for (k = 0; k < roughnessSamples; k++) { // Calculate roughness ... roughness = (GLUSfloat)k * 1.0f / (GLUSfloat)(roughnessSamples - 1); printf("Roughness: %f\n", roughness); // ... and set it up for compute shader. glUniform1f(roughnessLocation, roughness); // Run the compute shader, which is doing the pre-filtering. glDispatchCompute(length / localSize, length / localSize, 1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureLambert); if (roughness == 0.0f) { // Compute shader stores result in given texture. glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colorBufferLambert); } glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureCookTorrance); // Compute shader stores result in given texture. glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colorBufferCookTorrance); // Resolve for (p = 0; p < length; p++) { for (q = 0; q < length; q++) { // Some of the textures need to be stored flipped and mirrored down. switch (i) { case 0: case 1: case 4: case 5: // Positive X // Negative X // Positive Z // Negative Z x = length - 1 - q; y = length - 1 - p; break; case 2: case 3: // Positive Y // Negative Y x = q; y = p; break; } for (o = 0; o < stride; o++) { if (isHDR) { if (roughness == 0.0f) { hdrOutput[0].data[p * length * stride + q * stride + o] = colorBufferLambert[y * length * 4 + x * 4 + o]; } hdrOutput[1].data[p * length * stride + q * stride + o] = colorBufferCookTorrance[y * length * 4 + x * 4 + o]; } else { if (roughness == 0.0f) { tgaOutput[0].data[p * length * stride + q * stride + o] = (GLUSubyte)glusClampf(colorBufferLambert[y * length * 4 + x * 4 + o] * 255.0f, 0.0f, 255.0f); } tgaOutput[1].data[p * length * stride + q * stride + o] = (GLUSubyte)glusClampf(colorBufferCookTorrance[y * length * 4 + x * 4 + o] * 255.0f, 0.0f, 255.0f); } } } } // Construct save name depending on roughness level. buffer[ouputLength + 7] = '0' + (k / 10); buffer[ouputLength + 8] = '0' + (k % 10); if (isHDR) { if (roughness == 0.0f) { buffer[ouputLength + 10] = 'd'; glusSaveHdrImage(buffer, &hdrOutput[0]); } buffer[ouputLength + 10] = 's'; glusSaveHdrImage(buffer, &hdrOutput[1]); } else if (roughness == 0.0f) { if (roughness == 0.0f) { buffer[ouputLength + 10] = 'd'; glusSaveTgaImage(buffer, &tgaOutput[0]); } buffer[ouputLength + 10] = 's'; glusSaveTgaImage(buffer, &tgaOutput[1]); } } } printf("completed!\n"); // // Freeing resources // free(scanVectors); free(colorBufferLambert); free(colorBufferCookTorrance); glusDestroyProgram(&computeProgram); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); if (g_cubemap) { glDeleteTextures(1, &g_cubemap); g_cubemap = 0; } glBindTexture(GL_TEXTURE_2D, 0); if (textureLambert) { glDeleteTextures(1, &textureLambert); textureLambert = 0; } if (textureCookTorrance) { glDeleteTextures(1, &textureCookTorrance); textureCookTorrance = 0; } if (isHDR) { glusDestroyHdrImage(&hdrOutput[0]); glusDestroyHdrImage(&hdrOutput[1]); } else { glusDestroyTgaImage(&tgaOutput[0]); glusDestroyTgaImage(&tgaOutput[1]); } glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); if (scanVectorsSSBO) { glDeleteBuffers(1, &scanVectorsSSBO); scanVectorsSSBO = 0; } // // Shutdown OpenGL. // glusShutdown(); return 0; }
GLUSboolean init(GLUSvoid) { GLUSshape backgroundSphere; GLUSshape wavefront; // 6 sides of diffuse and specular; all roughness levels of specular. GLUShdrimage image[6 * NUMBER_ROUGHNESS + 6]; // The look up table (LUT) is stored in a raw binary file. GLUSbinaryfile rawimage; GLUStextfile vertexSource; GLUStextfile fragmentSource; GLchar buffer[27] = "doge2/doge2_POS_X_00_s.hdr"; GLint i, k, m; // glusLoadTextFile("../Example33/shader/brdf.vert.glsl", &vertexSource); glusLoadTextFile("../Example33/shader/brdf.frag.glsl", &fragmentSource); glusBuildProgramFromSource(&g_modelProgram, (const GLchar**)&vertexSource.text, 0, 0, 0, (const GLchar**)&fragmentSource.text); glusDestroyTextFile(&vertexSource); glusDestroyTextFile(&fragmentSource); g_viewProjectionMatrixModelLocation = glGetUniformLocation(g_modelProgram.program, "u_viewProjectionMatrix"); g_modelMatrixModelLocation = glGetUniformLocation(g_modelProgram.program, "u_modelMatrix"); g_normalMatrixModelLocation = glGetUniformLocation(g_modelProgram.program, "u_normalMatrix"); g_eyeModelLocation = glGetUniformLocation(g_modelProgram.program, "u_eye"); g_textureSpecularModelLocation = glGetUniformLocation(g_modelProgram.program, "u_textureSpecular"); g_textureDiffuseModelLocation = glGetUniformLocation(g_modelProgram.program, "u_textureDiffuse"); g_textureLUTModelLocation = glGetUniformLocation(g_modelProgram.program, "u_textureLUT"); g_colorMaterialModelLocation = glGetUniformLocation(g_modelProgram.program, "u_colorMaterial"); g_roughnessMaterialModelLocation = glGetUniformLocation(g_modelProgram.program, "u_roughnessMaterial"); g_roughnessScaleModelLocation = glGetUniformLocation(g_modelProgram.program, "u_roughnessScale"); g_R0MaterialModelLocation = glGetUniformLocation(g_modelProgram.program, "u_R0Material"); g_vertexModelLocation = glGetAttribLocation(g_modelProgram.program, "a_vertex"); g_normalModelLocation = glGetAttribLocation(g_modelProgram.program, "a_normal"); // glusLoadTextFile("../Example33/shader/fullscreen.vert.glsl", &vertexSource); glusLoadTextFile("../Example33/shader/fullscreen.frag.glsl", &fragmentSource); glusBuildProgramFromSource(&g_fullscreenProgram, (const GLchar**)&vertexSource.text, 0, 0, 0, (const GLchar**)&fragmentSource.text); glusDestroyTextFile(&vertexSource); glusDestroyTextFile(&fragmentSource); // g_framebufferTextureFullscreenLocation = glGetUniformLocation(g_fullscreenProgram.program, "u_framebufferTexture"); g_msaaSamplesFullscreenLocation = glGetUniformLocation(g_fullscreenProgram.program, "u_msaaSamples"); g_exposureFullscreenLocation = glGetUniformLocation(g_fullscreenProgram.program, "u_exposure"); g_gammaFullscreenLocation = glGetUniformLocation(g_fullscreenProgram.program, "u_gamma"); // // glusLoadTextFile("../Example33/shader/background.vert.glsl", &vertexSource); glusLoadTextFile("../Example33/shader/background.frag.glsl", &fragmentSource); glusBuildProgramFromSource(&g_backgroundProgram, (const GLUSchar**)&vertexSource.text, 0, 0, 0, (const GLUSchar**)&fragmentSource.text); glusDestroyTextFile(&vertexSource); glusDestroyTextFile(&fragmentSource); // g_viewProjectionMatrixBackgroundLocation = glGetUniformLocation(g_backgroundProgram.program, "u_viewProjectionMatrix"); g_textureBackgroundLocation = glGetUniformLocation(g_backgroundProgram.program, "u_texture"); g_vertexBackgroundLocation = glGetAttribLocation(g_backgroundProgram.program, "a_vertex"); // // Setting up the full screen frame buffer. // glGenTextures(1, &g_fullscreenTexture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, g_fullscreenTexture); // Create MSAA texture. glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, MSAA_SAMPLES, GL_RGB32F, SCREEN_WIDTH, SCREEN_HEIGHT, GL_TRUE); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); // No need to access the depth buffer, so a render buffer is sufficient. glGenRenderbuffers(1, &g_fullscreenDepthRenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, g_fullscreenDepthRenderbuffer); glRenderbufferStorageMultisample(GL_RENDERBUFFER, MSAA_SAMPLES, GL_DEPTH_COMPONENT, SCREEN_WIDTH, SCREEN_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, 0); // glGenFramebuffers(1, &g_fullscreenFBO); glBindFramebuffer(GL_FRAMEBUFFER, g_fullscreenFBO); // Attach the color buffer ... glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, g_fullscreenTexture, 0); // ... and the depth buffer. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, g_fullscreenDepthRenderbuffer); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { printf("GL_FRAMEBUFFER_COMPLETE error 0x%x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); return GLUS_FALSE; } glBindFramebuffer(GL_FRAMEBUFFER, 0); // // // for (i = 0; i < 2; i++) { if (i == 0) { buffer[21] = 's'; } else { buffer[21] = 'd'; } for (k = 0; k < NUMBER_ROUGHNESS; k++) { if (i == 1 && k > 0) { continue; } buffer[18] = '0' + k / 10; buffer[19] = '0' + k % 10; for (m = 0; m < 6; m++) { if (m % 2 == 0) { buffer[12] = 'P'; buffer[13] = 'O'; buffer[14] = 'S'; } else { buffer[12] = 'N'; buffer[13] = 'E'; buffer[14] = 'G'; } switch (m) { case 0: case 1: buffer[16] = 'X'; break; case 2: case 3: buffer[16] = 'Y'; break; case 4: case 5: buffer[16] = 'Z'; break; } printf("Loading '%s' ...", buffer); if (!glusLoadHdrImage(buffer, &image[i*NUMBER_ROUGHNESS*6 + k*6 + m])) { printf(" error!\n"); continue; } printf(" done.\n"); } } } glGenTextures(1, &g_texture[0]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, g_texture[0]); glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGB32F, image[0].width, image[0].height, 6*NUMBER_ROUGHNESS, 0, GL_RGB, GL_FLOAT, 0); glusLogPrintError(GLUS_LOG_INFO, "glTexImage3D()"); for (i = 0; i < NUMBER_ROUGHNESS; i++) { for (k = 0; k < 6; k++) { glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 6*i + k, image[i*6 + k].width, image[i*6 + k].height, 1, image[i*6 + k].format, GL_FLOAT, image[i*6 + k].data); glusLogPrintError(GLUS_LOG_INFO, "glTexSubImage3D() %d %d", i, k); } } glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); // glGenTextures(1, &g_texture[1]); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_CUBE_MAP, g_texture[1]); for (i = 0; i < 6; i++) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, image[i + 6*NUMBER_ROUGHNESS].format, image[i + 6*NUMBER_ROUGHNESS].width, image[i + 6*NUMBER_ROUGHNESS].height, 0, image[i + 6*NUMBER_ROUGHNESS].format, GL_FLOAT, image[i + 6*NUMBER_ROUGHNESS].data); glusLogPrintError(GLUS_LOG_INFO, "glTexImage2D() %d", i); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); // printf("Loading 'doge2/EnvironmentBRDF_1024.data' ..."); if (!glusLoadBinaryFile("doge2/EnvironmentBRDF_1024.data", &rawimage)) { printf(" error!\n"); } else { printf(" done.\n"); } glGenTextures(1, &g_texture[2]); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, g_texture[2]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 1024, 1024, 0, GL_RG, GL_FLOAT, (GLfloat*)rawimage.binary); glusLogPrintError(GLUS_LOG_INFO, "glTexImage2D()"); 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); glusDestroyBinaryFile(&rawimage); // for (i = 0; i < 2; i++) { for (k = 0; k < NUMBER_ROUGHNESS; k++) { if (i == 1 && k > 0) { continue; } for (m = 0; m < 6; m++) { glusDestroyHdrImage(&image[i*NUMBER_ROUGHNESS*6 + k*6 + m]); } } } // glusCreateSpheref(&backgroundSphere, 500.0f, 32); g_numberIndicesBackground = backgroundSphere.numberIndices; glGenBuffers(1, &g_verticesBackgroundVBO); glBindBuffer(GL_ARRAY_BUFFER, g_verticesBackgroundVBO); glBufferData(GL_ARRAY_BUFFER, backgroundSphere.numberVertices * 4 * sizeof(GLfloat), (GLfloat*)backgroundSphere.vertices, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenBuffers(1, &g_indicesBackgroundVBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesBackgroundVBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, backgroundSphere.numberIndices * sizeof(GLuint), (GLuint*)backgroundSphere.indices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glusDestroyShapef(&backgroundSphere); // // // Use a helper function to load an wavefront object file. glusLoadObjFile("venusm.obj", &wavefront); g_numberVerticesModel = wavefront.numberVertices; glGenBuffers(1, &g_verticesModelVBO); glBindBuffer(GL_ARRAY_BUFFER, g_verticesModelVBO); glBufferData(GL_ARRAY_BUFFER, wavefront.numberVertices * 4 * sizeof(GLfloat), (GLfloat*)wavefront.vertices, GL_STATIC_DRAW); glGenBuffers(1, &g_normalsModelVBO); glBindBuffer(GL_ARRAY_BUFFER, g_normalsModelVBO); glBufferData(GL_ARRAY_BUFFER, wavefront.numberVertices * 3 * sizeof(GLfloat), (GLfloat*)wavefront.normals, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glusDestroyShapef(&wavefront); // glUseProgram(g_modelProgram.program); glUniform4fv(g_eyeModelLocation, 1, g_eye); glUniform1i(g_textureSpecularModelLocation, 0); glUniform1i(g_textureDiffuseModelLocation, 1); glUniform1i(g_textureLUTModelLocation, 2); glUniform1f(g_roughnessScaleModelLocation, (GLfloat)(NUMBER_ROUGHNESS - 1)); glGenVertexArrays(1, &g_modelVAO); glBindVertexArray(g_modelVAO); glBindBuffer(GL_ARRAY_BUFFER, g_verticesModelVBO); glVertexAttribPointer(g_vertexModelLocation, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_vertexModelLocation); glBindBuffer(GL_ARRAY_BUFFER, g_normalsModelVBO); glVertexAttribPointer(g_normalModelLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_normalModelLocation); // glUseProgram(g_fullscreenProgram.program); glUniform1i(g_framebufferTextureFullscreenLocation, 0); glUniform1i(g_msaaSamplesFullscreenLocation, MSAA_SAMPLES); glGenVertexArrays(1, &g_fullscreenVAO); glBindVertexArray(g_fullscreenVAO); // glUseProgram(g_backgroundProgram.program); glUniform1i(g_textureBackgroundLocation, 0); glGenVertexArrays(1, &g_backgroundVAO); glBindVertexArray(g_backgroundVAO); glBindBuffer(GL_ARRAY_BUFFER, g_verticesBackgroundVBO); glVertexAttribPointer(g_vertexBackgroundLocation, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_vertexBackgroundLocation); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesBackgroundVBO); // glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glEnable(GL_CULL_FACE); return GLUS_TRUE; }