void KeyComputeShader::execute() { glUseProgram(this->key_compute_shader); // Bind the output texture glBindImageTexture(0, // Binding image unit this->k_texture, // Texture to be bound 0, // Level GL_FALSE, // Layered? 0, // specified layer GL_WRITE_ONLY, // Access method GL_R16UI); // Format // Bind depth texture glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, this->depth_texture); /* GLfloat z_value[1024 * 4]; glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, z_value); */ // Compute results glDispatchCompute(this->n_tiles.x, this->n_tiles.y, 1); glMemoryBarrier(GL_ALL_BARRIER_BITS); // Bind texture glBindImageTexture(0, 0, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R16UI); // Check if values are correctly written /* GLushort value[1024]; glBindTexture(GL_TEXTURE_2D, this->k_texture); glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, value); glBindTexture(GL_TEXTURE_2D, 0); */ glUseProgram(0); }
int positiongen_launch( float t, GLuint vbo, int width, int height ) { debuggl_check( glUseProgram(positiongen.program) ); debuggl_check( glUniform1f(positiongen.u_time, t) ); debuggl_check( glBindBufferBase(GL_SHADER_STORAGE_BUFFER, positiongen.w_output, vbo) ); debuggl_check( glDispatchCompute(width/16, height/16, 1) ); debuggl_check( glBindBufferBase(GL_SHADER_STORAGE_BUFFER, positiongen.w_output, 0) ); debuggl_check( glUseProgram(0) ); }
void BackgroundSubtractorLOBSTER_<ParallelUtils::eGLSL>::dispatch(size_t nStage, GLShader& oShader) { lvDbgExceptionWatch; glAssert(nStage<m_nComputeStages); if(nStage==0) { if(m_dCurrLearningRate>0) oShader.setUniform1ui("nResamplingRate",(GLuint)ceil(m_dCurrLearningRate)); else oShader.setUniform1ui("nResamplingRate",BGSLOBSTER_DEFAULT_LEARNING_RATE); } else //nStage==1 && BGSLOBSTER_GLSL_USE_POSTPROC glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); glDispatchCompute((GLuint)ceil((float)m_oFrameSize.width/m_vDefaultWorkGroupSize.x),(GLuint)ceil((float)m_oFrameSize.height/m_vDefaultWorkGroupSize.y),1); }
void DynamicMarchingTetrahedra::update(GLContext * gl) { GLContext::Program * prog = gl->getProgram(m_sceneShader.c_str()); prog->use(); Vec3i numBlocks(64); Vec3i threadBlockSize(4); Vec3i gridSize = (numBlocks + threadBlockSize - 1) / threadBlockSize; gl->setUniform(prog->getUniformLoc("cubeInfo"), m_cubeInfo); gl->setUniform(prog->getUniformLoc("isPrefixSumPass"), true); gl->setUniform(prog->getUniformLoc("numCubes"), numBlocks); gl->setUniform(prog->getUniformLoc("sync1"), m_disp1); gl->setUniform(prog->getUniformLoc("sync2"), m_disp2); gl->setUniform(prog->getUniformLoc("sync3"), m_disp3); gl->setUniform(prog->getUniformLoc("sync4"), m_disp4); gl->setUniform(prog->getUniformLoc("maxTetrahedras"), 6); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffers[DMT_Buffer_Types::INDEX_BUFFER]); glDispatchCompute(gridSize.x, gridSize.y, gridSize.z); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); GPUPrefixScan::scan(gl, m_buffers[DMT_Buffer_Types::INDEX_BUFFER], m_buffers[DMT_Buffer_Types::BLOCK_BUFFER], 100*100*100); prog->use(); gl->setUniform(prog->getUniformLoc("isPrefixSumPass"), false); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffers[DMT_Buffer_Types::MESH_BUFFER]); glDispatchCompute(gridSize.x, gridSize.y, gridSize.z); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); m_numTriangles = GPUPrefixScan::getSum(gl, m_buffers[DMT_Buffer_Types::BLOCK_BUFFER]); }
void ComputeBasicGLSL::runComputeFilter(GLuint inputTex, GLuint outputTex, int width, int height) { glUseProgram( m_computeProg->getProgram() ); glBindImageTexture(0, inputTex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8); glBindImageTexture(1, outputTex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); glDispatchCompute(width/WORKGROUP_SIZE, height/WORKGROUP_SIZE, 1); glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); CHECK_GL_ERROR(); }
void SSAO::Update(const FrameBuffer *FBO, const Camera *camera) const { ssaoFBO.Bind(); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); Shader *ssao = Manager::Shader->GetShader("ssao"); ssao->Use(); ssao->BindTexturesUnits(); ssaoFBO.SendResolution(ssao); camera->BindViewMatrix(ssao->loc_view_matrix); camera->BindProjectionMatrix(ssao->loc_projection_matrix); camera->BindProjectionDistances(ssao); glUniform1f(ssao->loc_u_rad, radius); glUniform1i(ssao->loc_kernel_size, kernelSize); glUniform3fv(ssao->loc_kernel, kernelSize * 3, glm::value_ptr(kernel[0])); FBO->BindTexture(3, GL_TEXTURE0); FBO->BindTexture(4, GL_TEXTURE1); FBO->BindDepthTexture(GL_TEXTURE2); RandomNoise1->BindToTextureUnit(GL_TEXTURE3); RandomNoise2->BindToTextureUnit(GL_TEXTURE4); ScreenQuad->Render(ssao); // Finish TASK glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); FrameBuffer::Unbind(); // -- COMPUTE SHADER int WORK_GROUP_SIZE = 16; auto res = ssaoFBO.GetResolution(); Shader *S = Manager::Shader->GetShader("ssaoBlur"); S->Use(); // First Pass ssaoFBO.BindTexture(0, GL_TEXTURE0); glBindImageTexture(1, computeTexture->GetTextureID(), 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA16F); glDispatchCompute(GLuint(UPPER_BOUND(res.x, WORK_GROUP_SIZE)), GLuint(UPPER_BOUND(res.y, WORK_GROUP_SIZE)), 1); glMemoryBarrier(GL_ALL_BARRIER_BITS); }
GLUSboolean update(GLUSfloat time) { // Switch to the compute shader. glUseProgram(g_computeProgram.program); // Create threads depending on width, height and block size. In this case we have 1200 threads. glDispatchCompute(g_imageWidth / g_localSize, g_imageHeight / g_localSize, 1); // Switch back to the render program. glUseProgram(g_program.program); // Here we full screen the output of the compute shader. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); return GLUS_TRUE; }
void GraphicsEngine::GridComputePass(const glm::mat4& projMatrix) { int workGroupsX = (SCREEN_SIZE_X + (SCREEN_SIZE_X % GRID_SIZE)) / GRID_SIZE; int workGroupsY = (SCREEN_SIZE_Y + (SCREEN_SIZE_Y % GRID_SIZE)) / GRID_SIZE; GraphicsCore::GPUAPI::UseShader(g_GridComputeProgram); // Setup inverse projection Matrix. glm::mat4 projInv = glm::inverse(projMatrix); glUniformMatrix4fv(glGetUniformLocation(g_GridComputeProgram, "inverseProj"), 1, GL_FALSE, glm::value_ptr(projInv)); glUniform2f(glGetUniformLocation(g_GridComputeProgram, "screenDimensions"), SCREEN_SIZE_X, SCREEN_SIZE_Y); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, g_FrustrumSSBO.SSBO); glDispatchCompute(workGroupsX, workGroupsY, 1); }
void HeightMapCS::GenerateHeightMap() { mShader.Use(); glUniform1f(mShader.GetUniform(u_Time), Engine::GetInstance()->GetTime()); GL_CHECK_ERRORS; glBindImageTexture((GLuint)EHMapCSBindings::u_ImageOut, mHeightMapTextureId, 0, GL_FALSE, 0, GL_WRITE_ONLY, mPrecomputeNormals ? GL_RGBA16F : GL_R16F); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, (GLuint)EHMapCSBindings::u_WaveParamsBlock, mBufferIds[WavePropsBufferIndex]); GL_CHECK_ERRORS; //glDispatchCompute(mTextureSize.x / 32, mTextureSize.y / 32, 1); glDispatchCompute(mTextureSize.x, mTextureSize.y, 1); glBindTexture(GL_TEXTURE_2D, 0); mShader.UnUse(); }
void SimpleComputeShaderExample::Display(bool auto_redraw) { // Activate the compute program and bind the output texture image glUseProgram(compute_prog); glBindImageTexture(0, output_image, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); glDispatchCompute(8, 16, 1); // Now bind the texture for rendering _from_ glBindTexture(GL_TEXTURE_2D, output_image); // Clear, select the rendering program and draw a full screen quad glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(render_prog); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); base::Display(); }
// This runs once a frame, before renderScene void update() { // If we're reversing the circle that means we are shrinking it. // This part of the code should be straightforward: frameNum will increase until 250, then decrease down to 1, then repeat if (reverse) { frameNum--; if (frameNum < 1) { reverse = false; } } else { frameNum++; if (frameNum > 250) { reverse = true; } } // Rotate the transformation matrix about the Z axis by 1 degree per function call. // glm::rotate returns a 4x4 matrix of the resulting transform, given an input matrix, an angle to rotate by (in radians), and a vector3 determining which axis to rotate about // glm::radians converts the value in paranthesis from degrees to radians // The axis parameter should be treated like a vector, so it doesn't just have to have a 1.0f in a single axis, but instead you're defining a vector that we are rotating around trans = glm::rotate(trans, glm::radians(1.0f), glm::vec3(0.0f, 0.0f, 1.0f)); // All this is doing is rotating the circle. // This takes the value of our transformation, view, and projection matrices and multiplies them together to create the MVP matrix. // Then it sets our uniform MVP matrix within our shader to this value. // Parameters are: Location within the shader, size (in case we're passing in multiple matrices via a single pointer), whether or not to transpose the matrix, and a pointer // to the matrix value we're passing in. MVP = proj * view * trans; // Tells the code to use the compute shader program. glUseProgram(compute_program); // Sets the uniform radius to frameNum / 500. glUniform1f(iLocRadius, ((float)frameNum / 500.0f)); // Submit job for the compute shader execution. // GROUP_SIZE_HEIGHT = GROUP_SIZE_WIDTH = 8 // NUM_VERTS_H = NUM_VERTS_V = 16 // As the result the function is called with the following parameters: glDispatchCompute(2, 2, 1); // 2 x 2 = 4, and within the compute shader we've locally defined sizes x and y to be 8, so 8 x 8 = 64 and 64 x 4 = 256 }
void ScanSystem::combineWithOffsets(GLuint elements, const Buffer& output, const Buffer& offsets ) { //assert((elements % 4) == 0); assert(elements * sizeof(GLuint) <= output.size); glUseProgram(programs.combine); glUniform1ui(0,elements); offsets.BindBufferRange(GL_SHADER_STORAGE_BUFFER, 1); output.BindBufferRange(GL_SHADER_STORAGE_BUFFER, 0); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); GLuint groups = snapdiv(elements,GROUPSIZE); assert(groups < maxGrpsCombine); glDispatchCompute(groups,1,1); }
bool GLComputeEvaluator::EvalPatches( GLuint srcBuffer, BufferDescriptor const &srcDesc, GLuint dstBuffer, BufferDescriptor const &dstDesc, GLuint duBuffer, BufferDescriptor const &duDesc, GLuint dvBuffer, BufferDescriptor const &dvDesc, int numPatchCoords, GLuint patchCoordsBuffer, const PatchArrayVector &patchArrays, GLuint patchIndexBuffer, GLuint patchParamsBuffer) const { if (!_patchKernel.program) return false; glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, patchCoordsBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, patchIndexBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, patchParamsBuffer); glUseProgram(_patchKernel.program); glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset); glUniform1i(_patchKernel.uniformDstOffset, dstDesc.offset); glUniform4iv(_patchKernel.uniformPatchArray, (int)patchArrays.size(), (const GLint*)&patchArrays[0]); glUniform3i(_patchKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride); glUniform3i(_patchKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride); glDispatchCompute((numPatchCoords + _workGroupSize - 1) / _workGroupSize, 1, 1); glUseProgram(0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, 0); return true; }
void CParticlePropNode::bindAndDraw() { glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_vboId); m_updateShader->bind(); glDispatchCompute(512/16, 1, 1); glPointSize(3.0f); m_drawShader->bind(); CShaderResource::glslSendInt("max_particles", 512); glBindBufferBase(GL_UNIFORM_BUFFER, OPENGL_UBOBP_PROP, m_uboId); CVaoBinder::bind(m_vaoId); glDrawArrays(GL_POINTS, 0, 512); glPointSize(1.0f); }
/*!**************************************************************************** @Function Update @Input dt Elapsed time from last iteration (frame) @Description Advances the simulation by dt. Invalidates the following OpenGL state:Current program, GL_UNIFORM_BUFFER binding ******************************************************************************/ void ParticleSystemGPU::Update(float dt) { if (dt == 0) { return; } dt *= 0.001f; GLuint numGroups = m_ui32NumParticles / m_ui32WorkgroupSize; m_ParticleConfigData.fDt = dt; m_ParticleConfigData.fTotalTime += dt; glBindBuffer(GL_UNIFORM_BUFFER, m_ParticleConfigUbo); glBufferData(GL_UNIFORM_BUFFER, sizeof(m_ParticleConfigData), &m_ParticleConfigData, GL_STREAM_DRAW); glUseProgram(m_glProgram); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); glDispatchCompute(numGroups, 1, 1); glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT); }
GLUSboolean update(GLUSfloat time) { glClear(GL_COLOR_BUFFER_BIT); // Switch to the compute shader. glUseProgram(g_computeProgram.program); // Create threads depending on width, height and block size. In this case we have 1200 threads. glDispatchCompute(g_imageWidth / g_localSize, g_imageHeight / g_localSize, 1); // Switch back to the render program. glUseProgram(g_program.program); // Here we draw the plane / rectangle using the indices, stored in the VBO. glDrawElements(GL_TRIANGLES, g_numberIndicesPlane, GL_UNSIGNED_INT, 0); return GLUS_TRUE; }
void v_Render() { float t = (float)glfwGetTime(); static const float black[] = { 0.0f, 0.0f, 0.0f, 1.0f }; static const float one = 1.0f; glUseProgram(flock_update_program); vmath::vec3 goal = vmath::vec3(sinf(t * 0.34f), cosf(t * 0.29f), sinf(t * 0.12f) * cosf(t * 0.5f)); goal = goal * vmath::vec3(35.0f, 25.0f, 60.0f); glUniform3fv(uniforms.update.goal, 1, goal); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, flock_buffer[frame_index]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, flock_buffer[frame_index ^ 1]); glDispatchCompute(NUM_WORKGROUPS, 1, 1); glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); glClearBufferfv(GL_COLOR, 0, black); glClearBufferfv(GL_DEPTH, 0, &one); glUseProgram(flock_render_program); vmath::mat4 mv_matrix = vmath::lookat(vmath::vec3(0.0f, 0.0f, -400.0f), vmath::vec3(0.0f, 0.0f, 0.0f), vmath::vec3(0.0f, 1.0f, 0.0f)); vmath::mat4 proj_matrix = vmath::perspective(60.0f, getAspect(), 0.1f, 3000.0f); vmath::mat4 mvp = proj_matrix * mv_matrix; glUniformMatrix4fv(uniforms.render.mvp, 1, GL_FALSE, mvp); glBindVertexArray(flock_render_vao[frame_index]); glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 8, FLOCK_SIZE); frame_index ^= 1; }
void display() { // Update of the uniform buffer { glBindBuffer(GL_UNIFORM_BUFFER, BufferName[buffer::TRANSFORM]); glm::mat4* Pointer = (glm::mat4*)glMapBufferRange( GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); glm::mat4 Projection = glm::perspectiveFov(45.f, 640.f, 480.f, 0.1f, 100.0f); //glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f); glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Window.TranlationCurrent.y)); glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Window.RotationCurrent.y, glm::vec3(1.f, 0.f, 0.f)); glm::mat4 View = glm::rotate(ViewRotateX, Window.RotationCurrent.x, glm::vec3(0.f, 1.f, 0.f)); glm::mat4 Model = glm::mat4(1.0f); *Pointer = Projection * View * Model; // Make sure the uniform buffer is uploaded glUnmapBuffer(GL_UNIFORM_BUFFER); } glBindProgramPipeline(PipelineName[program::COMPUTE]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, semantics::INPUT, BufferName[buffer::INPUT]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, semantics::OUTPUT, BufferName[buffer::OUTPUT]); glBindBufferBase(GL_UNIFORM_BUFFER, glf::semantic::uniform::TRANSFORM0, BufferName[buffer::TRANSFORM]); glDispatchCompute(GLuint(VertexCount), 1, 1); glViewportIndexedf(0, 0, 0, GLfloat(Window.Size.x), GLfloat(Window.Size.y)); glClearBufferfv(GL_COLOR, 0, &glm::vec4(1.0f)[0]); glBindProgramPipeline(PipelineName[program::GRAPHICS]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, TextureName); glBindVertexArray(VertexArrayName); glBindBufferBase(GL_UNIFORM_BUFFER, glf::semantic::uniform::TRANSFORM0, BufferName[buffer::TRANSFORM]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, semantics::INPUT, BufferName[buffer::OUTPUT]); glDrawElementsInstancedBaseVertexBaseInstance( GL_TRIANGLES, ElementCount, GL_UNSIGNED_SHORT, GLF_BUFFER_OFFSET(0), 1, 0, 0); glf::swapBuffers(); }
void Game::UpdateFrame( const double deltaTimeSec) { if(GLEW_ARB_compute_shader) { m_cameraDataUBO->Bind( m_computeShaderProgram->GetUniformBlockIndex("CameraInfo")); glBindImageTexture( 0, m_texture->GetTextureID(), 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); m_computeShaderProgram->Bind(); glDispatchCompute( 1280 / 8, 720 / 8, 1); m_computeShaderProgram->UnBind(); glBindImageTexture( 0, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); m_cameraDataUBO->UnBind(); } }
void TiledLightRenderer::draw(const vector<Light>& lights, Texture* processedSkybox) { createLigthBuffer(lights); _lightBuffer.bind(0); _computeShader->bind(); _computeShader->setUniform(static_cast<int>(lights.size()), _nbLightUniformId); openGL.bindImageTexture(_buffer.buffer(0)->id(), 0, GL_WRITE_ONLY, Texture::toGLFormat(_buffer.buffer(0)->format())); for(int i=0 ; i<4 ; ++i) { openGL.bindTextureSampler(textureSampler[TextureMode::NoFilter], i); _deferred.buffer(i)->bind(i); } if(_processedBrdf) { _processedBrdf->bind(4); openGL.bindTextureSampler(textureSampler[TextureMode::FilteredNoRepeat], 4); } else openGL.bindTexture(0, GL_TEXTURE_2D, 4); if(processedSkybox) { processedSkybox->bind(5); openGL.bindTextureSampler(textureSampler[TextureMode::FilteredNoRepeat], 5); } else openGL.bindTexture(0, GL_TEXTURE_CUBE_MAP, 5); uint texIndex=6; for(const Light& l : lights) { if(l.type == Light::SPECULAR_PROB && l.tex != nullptr) { openGL.bindTextureSampler(textureSampler[TextureMode::FilteredNoRepeat], texIndex); l.tex->bind(texIndex++); } } _frameState.bind(0); glDispatchCompute(_tileCount.x(),_tileCount.y(),1); glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); }
void convertToSphericalMaps( const GLCubeMapContainer<ChannelCount, HasDepthBuffer>& container, const GLTexture2DArray* sphereMapArrays) { m_ConvertPass.m_Program.use(); Vec3u groupSize(16, 16, 4); for(auto i = 0u; i < ChannelCount; ++i) { sphereMapArrays[i].bindImage(0u, 0, GL_WRITE_ONLY, GL_RGBA32F); m_ConvertPass.uSphereMap.set(0u); m_ConvertPass.uCubeMapContainer.set(i, 0u, container); glDispatchCompute(1 + sphereMapArrays[i].getWidth() / groupSize.x, 1 + sphereMapArrays[i].getHeight() / groupSize.y, 1 + container.size() / groupSize.z); } glMemoryBarrier(GL_ALL_BARRIER_BITS); }
void convertToDualParaboloidMaps( const GLCubeMapContainer<ChannelCount, HasDepthBuffer>& container, const GLBufferStorage<Vec4f>* dualParaboloidMapBuffers, uint32_t paraboloidMapWidth, uint32_t paraboloidMapHeight) { m_DualParaboloidConversionPass.m_Program.use(); Vec3u groupSize(16, 16, 4); for(auto i = 0u; i < ChannelCount; ++i) { dualParaboloidMapBuffers[i].bindBase(GL_SHADER_STORAGE_BUFFER, 0); m_DualParaboloidConversionPass.uCubeMapContainer.set(i, 0u, container); m_DualParaboloidConversionPass.uParaboloidMapWidth.set(paraboloidMapWidth); m_DualParaboloidConversionPass.uParaboloidMapHeight.set(paraboloidMapHeight); m_DualParaboloidConversionPass.uDualParaboloidMapCount.set(container.size()); glDispatchCompute(1 + 2 * paraboloidMapWidth / groupSize.x, 1 + paraboloidMapHeight / groupSize.y, 1 + container.size() / groupSize.z); } glMemoryBarrier(GL_ALL_BARRIER_BITS); }
void convertToSphericalMaps( const GLCubeMapContainer<ChannelCount, HasDepthBuffer>& container, const GLBufferStorage<Vec4f>* sphereMapBuffers, uint32_t sphereMapWidth, uint32_t sphereMapHeight) { m_ConvertPass2.m_Program.use(); Vec3u groupSize(16, 16, 4); for(auto i = 0u; i < ChannelCount; ++i) { sphereMapBuffers[i].bindBase(GL_SHADER_STORAGE_BUFFER, 0); m_ConvertPass2.uCubeMapContainer.set(i, 0u, container); m_ConvertPass2.uSphereMapWidth.set(sphereMapWidth); m_ConvertPass2.uSphereMapHeight.set(sphereMapHeight); m_ConvertPass2.uSphereMapCount.set(container.size()); glDispatchCompute(1 + sphereMapWidth / groupSize.x, 1 + sphereMapHeight / groupSize.y, 1 + container.size() / groupSize.z); } glMemoryBarrier(GL_ALL_BARRIER_BITS); }
void ParticleSystem::update() { // Invoke the compute shader to integrate the particles glBindProgramPipeline(m_programPipeline); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_3D, m_noiseTex); glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 1, m_pos->getBuffer() ); glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 2, m_vel->getBuffer() ); glDispatchCompute(GLuint (m_size / WORK_GROUP_SIZE), 1, 1 ); // We need to block here on compute completion to ensure that the // computation is done before we render glMemoryBarrier( GL_SHADER_STORAGE_BARRIER_BIT ); glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 2, 0 ); glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 1, 0 ); glBindProgramPipeline(0); }
bool render() { glm::vec2 WindowSize(this->getWindowSize()); { glBindBuffer(GL_UNIFORM_BUFFER, BufferName[buffer::TRANSFORM]); glm::mat4* Pointer = (glm::mat4*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); glm::mat4 Projection = glm::perspectiveFov(glm::pi<float>() * 0.25f, WindowSize.x, WindowSize.y, 0.1f, 100.0f); glm::mat4 Model = glm::mat4(1.0f); *Pointer = Projection * this->view() * Model; // Make sure the uniform buffer is uploaded glUnmapBuffer(GL_UNIFORM_BUFFER); } glBindProgramPipeline(PipelineName[program::COMPUTE]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, semantics::INPUT, BufferName[buffer::INPUT]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, semantics::OUTPUT, BufferName[buffer::OUTPUT]); glBindBufferBase(GL_UNIFORM_BUFFER, semantic::uniform::TRANSFORM0, BufferName[buffer::TRANSFORM]); glDispatchCompute(GLuint(VertexCount), 1, 1); glViewportIndexedf(0, 0, 0, WindowSize.x, WindowSize.y); glClearBufferfv(GL_COLOR, 0, &glm::vec4(1.0f)[0]); glBindProgramPipeline(PipelineName[program::GRAPHICS]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, TextureName); glBindVertexArray(VertexArrayName); glBindBufferBase(GL_UNIFORM_BUFFER, semantic::uniform::TRANSFORM0, BufferName[buffer::TRANSFORM]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, semantics::INPUT, BufferName[buffer::OUTPUT]); glDrawElementsInstancedBaseVertexBaseInstance(GL_TRIANGLES, ElementCount, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0), 1, 0, 0); return true; }
void ParticleSystem::update(float timeDelta) { static bool updated = false; if (!updated) { LOGI("ParticleSystem: First Update Time: %f", timeDelta); updated = true; } m_mcpolygonizer->generateMesh(m_pos, m_vel, timeDelta); // Invoke the compute shader to integrate the particles glBindProgramPipeline(m_programPipeline); glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 1, m_pos->getBuffer() ); glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 2, m_vel->getBuffer() ); // Update the timestep in the shaders GLuint loc = glGetUniformLocation(m_updateProg, "timeStep"); glProgramUniform1f(m_updateProg, loc, timeDelta); uint xGroups = (m_size + (WORK_GROUP_SIZE - 1)) / WORK_GROUP_SIZE; glDispatchCompute(xGroups, 1, 1); // We need to block here on compute completion to ensure that the // computation is done before we render glMemoryBarrier( GL_SHADER_STORAGE_BARRIER_BIT ); glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 2, 0 ); glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 1, 0 ); // Update the timestep in the shaders //GLuint loc = glGetUniformLocation(m_updateProg, "timeStep"); //glProgramUniform1f(m_updateProg, loc, timeDelta); glBindProgramPipeline(0); }
//-------------------------------------------------------------- void ofShader::dispatchCompute(GLuint x, GLuint y, GLuint z) const{ glDispatchCompute(x,y,z); }
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, ouputLength; GLUSuint x = 0; GLUSuint y = 0; GLUSboolean isHDR = GLUS_FALSE; GLUStgaimage tgaOutput[2]; GLUShdrimage hdrOutput[2]; GLUSboolean mipMap; 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; GLUSprogram computeProgram; GLUSuint localSize = 16; GLUSuint textureLambert; GLUSuint textureCookTorrance[MAX_ROUGHNESS]; GLUSuint scanVectorsSSBO; GLUSint mLocation; GLUSint samplesLocation; GLUSint binaryFractionFactorLocation; GLUSint roughnessLocation; EGLint eglConfigAttributes[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE }; EGLint eglContextAttributes[] = { EGL_CONTEXT_MAJOR_VERSION, 4, EGL_CONTEXT_MINOR_VERSION, 3, EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE, EGL_TRUE, EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, EGL_NONE }; if (argc != 12) { printf("Usage: PreFilterCubeMap.exe [Pos X] [Neg X] [Pos Y] [Neg Y] [Pos Z] [Neg Z] [Output] [Roughness] [Samples 2^m] [Length 2^n] [As MipMap]\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 >= MAX_ROUGHNESS) { 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; mipMap = (GLUSuint)atoi(argv[11]) != 0; if (mipMap && roughnessSamples - 1 > lengthExponent) { printf("Error: Can not do mip mapping with given roughness and length.\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 (!glusImageLoadTga(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); glusImageDestroyTga(&tgaOutput[0]); return -1; } } else if (strcmp(fileType, ".hdr") == 0) { isHDR = GLUS_TRUE; for (i = 0; i < 6; i++) { if (!glusImageLoadHdr(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); glusImageDestroyHdr(&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. // if (!glusWindowCreate("GLUS Example Window", 512, 512, GLUS_FALSE, GLUS_FALSE, eglConfigAttributes, eglContextAttributes)) { printf("Could not create window!\n"); return -1; } if (!glusWindowStartup()) { return -1; } // // Compute shader for pre-filtering. // glusFileLoadText("../PreFilterCubeMap/shader/prefilter.comp.glsl", &computeSource); glusProgramBuildComputeFromSource(&computeProgram, (const GLchar**)&computeSource.text); glusFileDestroyText(&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); // if (mipMap) { // Prepare texture, where the pre-filtered image is stored: Cook-Torrance glGenTextures(roughnessSamples, textureCookTorrance); for (i = 0; i < roughnessSamples; i++) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureCookTorrance[i]); 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); length /= 2; } length = 1 << lengthExponent; } else { // Prepare texture, where the pre-filtered image is stored: Cook-Torrance glGenTextures(1, textureCookTorrance); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureCookTorrance[0]); 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], 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; } if (!mipMap) { // 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++) { if (mipMap) { if (isHDR) { hdrOutput[1].width = length; hdrOutput[1].height = length; } else { tgaOutput[1].width = length; tgaOutput[1].height = length; } step = 2.0f / (GLUSfloat)length; offset = step * 0.5f; // Generate scan vectors for (m = 0; m < length; m++) { for (o = 0; o < length; o++) { offsetVector[0] = 0.0f; offsetVector[1] = offset + step * (GLUSfloat)m; offsetVector[2] = offset + step * (GLUSfloat)o; glusVector3AddVector3f(normalVector, startVector, offsetVector); glusVector3Normalizef(normalVector); glusMatrix3x3MultiplyVector3f(&scanVectors[m * length * (3 + 1) + o * (3 + 1)], matrix, normalVector); } } // Upload scan vectors for each side. glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, length * length * (3 + 1) * sizeof(GLfloat), scanVectors); } // 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); if (mipMap) { // see binding = 2 in the shader glBindImageTexture(2, textureCookTorrance[k], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F); glPixelStorei(GL_PACK_ALIGNMENT, 1); } // 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); if (mipMap) { glBindTexture(GL_TEXTURE_2D, textureCookTorrance[k]); } else { glBindTexture(GL_TEXTURE_2D, textureCookTorrance[0]); } // 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)glusMathClampf(colorBufferLambert[y * length * 4 + x * 4 + o] * 255.0f, 0.0f, 255.0f); } tgaOutput[1].data[p * length * stride + q * stride + o] = (GLUSubyte)glusMathClampf(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'; glusImageSaveHdr(buffer, &hdrOutput[0]); } buffer[ouputLength + 10] = 's'; glusImageSaveHdr(buffer, &hdrOutput[1]); } else { if (roughness == 0.0f) { buffer[ouputLength + 10] = 'd'; glusImageSaveTga(buffer, &tgaOutput[0]); } buffer[ouputLength + 10] = 's'; glusImageSaveTga(buffer, &tgaOutput[1]); } if (mipMap) { length /= 2; } } if (mipMap) { length = 1 << lengthExponent; } } printf("completed!\n"); // // Freeing resources // free(scanVectors); free(colorBufferLambert); free(colorBufferCookTorrance); glusProgramDestroy(&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 (!mipMap) { if (textureCookTorrance[0]) { glDeleteTextures(1, textureCookTorrance); textureCookTorrance[0] = 0; } } else { glDeleteTextures(roughnessSamples, textureCookTorrance); } if (isHDR) { glusImageDestroyHdr(&hdrOutput[0]); glusImageDestroyHdr(&hdrOutput[1]); } else { glusImageDestroyTga(&tgaOutput[0]); glusImageDestroyTga(&tgaOutput[1]); } glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); if (scanVectorsSSBO) { glDeleteBuffers(1, &scanVectorsSSBO); scanVectorsSSBO = 0; } // // Shutdown OpenGL. // glusWindowShutdown(); return 0; }
GLUSboolean update(GLUSfloat time) { static GLfloat totalTime = 0.0f; static GLint previousInput = 0; static GLint currentInput = 1; static GLint currentOutput = 2; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_CULL_FACE); if (!updateSphere(time)) { return GLUS_FALSE; } glDisable(GL_CULL_FACE); // // Simulation part. // glUseProgram(g_computeProgram.program); glUniform1f(g_deltaTimeLocation, time); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_BUFFER_COMP_VERTICES_IN_PREVIOUS, g_verticesBuffer[previousInput]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_BUFFER_COMP_VERTICES_IN_CURRENT, g_verticesBuffer[currentInput]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_BUFFER_COMP_VERTICES_OUT, g_verticesBuffer[currentOutput]); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_BUFFER_COMP_NORMALS_OUT, g_normalsBuffer); // Process all vertices. glDispatchCompute(1, 1, 1); // Make sure, all vertices and normals are written. glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_BUFFER_COMP_VERTICES_IN_PREVIOUS, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_BUFFER_COMP_VERTICES_IN_CURRENT, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_BUFFER_COMP_VERTICES_OUT, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_BUFFER_COMP_NORMALS_OUT, 0); // // Drawing part. // glUseProgram(g_program.program); glBindVertexArray(g_vao); glBindBuffer(GL_ARRAY_BUFFER, g_verticesBuffer[currentOutput]); glVertexAttribPointer(g_vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0); glDrawElements(GL_TRIANGLES, g_numberIndicesPlane, GL_UNSIGNED_INT, 0); glBindVertexArray(0); // Output is next time input etc. previousInput = (previousInput + 1) % 3; currentInput = (currentInput + 1) % 3; currentOutput = (currentOutput + 1) % 3; // Update the total passed time. totalTime += time; // Reset after 10 seconds. if (totalTime >= 10.0f) { previousInput = 0; currentInput = 1; currentOutput = 2; glBindBuffer(GL_SHADER_STORAGE_BUFFER, g_verticesBuffer[previousInput]); glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, g_gridPlane.numberVertices * 4 * sizeof(GLfloat), g_gridPlane.vertices); glBindBuffer(GL_SHADER_STORAGE_BUFFER, g_verticesBuffer[currentInput]); glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, g_gridPlane.numberVertices * 4 * sizeof(GLfloat), g_gridPlane.vertices); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); totalTime = 0.0f; } return GLUS_TRUE; }
void FilterComputeShader::DispatchCompute(int width, int height, int depth) { glDispatchCompute(width, height, depth); }