bool InitScene() { SetWindowText(hwnd, TITLE); Quadron::qGLExtensions::QueryFeatures(hdc); hascompute = (Quadron::qGLExtensions::ARB_compute_shader && Quadron::qGLExtensions::ARB_shader_storage_buffer_object); #ifdef _DEBUG if( Quadron::qGLExtensions::ARB_debug_output ) { glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); glDebugMessageCallback(ReportGLError, 0); } #endif glClearColor(0.0f, 0.125f, 0.3f, 1.0f); glClearDepth(1.0); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); // load objects if( !GLCreateMeshFromQM("../media/meshes/teapot.qm", &teapot) ) { MYERROR("Could not load teapot"); return false; } if( !GLCreateMeshFromQM("../media/meshes/cube.qm", &box) ) { MYERROR("Could not load box"); return false; } // calculate scene bounding box OpenGLAABox tmpbox; float world[16]; float tmp[16]; GLMatrixIdentity(world); for( int i = 0; i < numobjects; ++i ) { const SceneObject& obj = objects[i]; // scaling * rotation * translation GLMatrixScaling(tmp, obj.scale[0], obj.scale[1], obj.scale[2]); GLMatrixRotationAxis(world, obj.angle, 0, 1, 0); GLMatrixMultiply(world, tmp, world); GLMatrixTranslation(tmp, obj.position[0], obj.position[1], obj.position[2]); GLMatrixMultiply(world, world, tmp); if( obj.type == 0 ) tmpbox = box->GetBoundingBox(); else if( obj.type == 1 ) tmpbox = teapot->GetBoundingBox(); tmpbox.TransformAxisAligned(world); scenebox.Add(tmpbox.Min); scenebox.Add(tmpbox.Max); } // create render targets framebuffer = new OpenGLFramebuffer(screenwidth, screenheight); framebuffer->AttachTexture(GL_COLOR_ATTACHMENT0, GLFMT_A16B16G16R16F); framebuffer->AttachTexture(GL_DEPTH_ATTACHMENT, GLFMT_D32F); if( !framebuffer->Validate() ) return false; shadowmap = new OpenGLFramebuffer(SHADOWMAP_SIZE, SHADOWMAP_SIZE); shadowmap->AttachTexture(GL_COLOR_ATTACHMENT0, GLFMT_G32R32F, GL_LINEAR); shadowmap->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, GLFMT_D24S8); if( !shadowmap->Validate() ) return false; blurredshadow = new OpenGLFramebuffer(SHADOWMAP_SIZE, SHADOWMAP_SIZE); blurredshadow->AttachTexture(GL_COLOR_ATTACHMENT0, GLFMT_G32R32F, GL_LINEAR); if( !blurredshadow->Validate() ) return false; screenquad = new OpenGLScreenQuad(); // textures if( !GLCreateTextureFromFile("../media/textures/wood2.jpg", true, &texture1) ) { MYERROR("Could not load texture"); return false; } if( !GLCreateTextureFromFile("../media/textures/marble2.png", true, &texture2) ) { MYERROR("Could not load texture"); return false; } if( !GLCreateTextureFromFile("../media/textures/static_sky.jpg", true, &texture3, GLTEX_FLIPX) ) { MYERROR("Could not load texture"); return false; } // create buffers workgroupsx = (screenwidth + (screenwidth % 16)) / 16; workgroupsy = (screenheight + (screenheight % 16)) / 16; size_t numtiles = workgroupsx * workgroupsy; size_t headsize = 16; // start, count, pad, pad size_t nodesize = 16; // light index, next, pad, pad if( hascompute ) { glGenBuffers(1, &headbuffer); glGenBuffers(1, &nodebuffer); glGenBuffers(1, &lightbuffer); glGenBuffers(1, &counterbuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, headbuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, numtiles * headsize, 0, GL_STATIC_DRAW); glBindBuffer(GL_SHADER_STORAGE_BUFFER, nodebuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, numtiles * nodesize * 1024, 0, GL_STATIC_DRAW); // 4 MB glBindBuffer(GL_SHADER_STORAGE_BUFFER, lightbuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, NUM_LIGHTS * sizeof(LightParticle), 0, GL_DYNAMIC_DRAW); UpdateParticles(0, true); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counterbuffer); glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), 0, GL_DYNAMIC_DRAW); glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0); } // load effects if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/basic2D.frag", &basic2D) ) { MYERROR("Could not load basic 2D shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/boxblur3x3.frag", &boxblur3x3) ) { MYERROR("Could not load blur shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/gammacorrect.frag", &gammacorrect) ) { MYERROR("Could not load gamma correction shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/shadowmap_variance.vert", 0, "../media/shadersGL/shadowmap_variance.frag", &varianceshadow) ) { MYERROR("Could not load shadowmap shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/blinnphong_variance.vert", 0, "../media/shadersGL/blinnphong_variance.frag", &shadowedlight) ) { MYERROR("Could not load shadowed light shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/ambient.vert", 0, "../media/shadersGL/ambient.frag", &ambient) ) { MYERROR("Could not load ambient shader"); return false; } if( hascompute ) { // light accumulation shader if( !GLCreateEffectFromFile("../media/shadersGL/lightaccum.vert", 0, "../media/shadersGL/lightaccum.frag", &lightaccum) ) { MYERROR("Could not load light accumulation shader"); return false; } // light culling shader if( !GLCreateComputeProgramFromFile("../media/shadersGL/lightcull.comp", &lightcull) ) { MYERROR("Could not load light culling shader"); return false; } lightcull->SetInt("depthSampler", 0); lightcull->SetInt("numLights", NUM_LIGHTS); lightaccum->SetInt("sampler0", 0); } float white[] = { 1, 1, 1, 1 }; shadowedlight->SetVector("matSpecular", white); shadowedlight->SetInt("sampler0", 0); shadowedlight->SetInt("sampler1", 1); boxblur3x3->SetInt("sampler0", 0); basic2D->SetInt("sampler0", 0); gammacorrect->SetInt("sampler0", 0); float angles[2] = { 0.25f, -0.7f }; cameraangle = angles; return true; }
bool InitScene() { SurfaceVertex* svdata = 0; float (*vdata)[4] = 0; GLushort* idata = 0; GLuint* idata32 = 0; OpenGLVertexElement decl[] = { { 0, 0, GLDECLTYPE_FLOAT4, GLDECLUSAGE_POSITION, 0 }, { 0xff, 0, 0, 0, 0 } }; OpenGLVertexElement decl2[] = { { 0, 0, GLDECLTYPE_FLOAT4, GLDECLUSAGE_POSITION, 0 }, { 0, 16, GLDECLTYPE_FLOAT4, GLDECLUSAGE_NORMAL, 0 }, { 0xff, 0, 0, 0, 0 } }; SetWindowText(hwnd, TITLE); Quadron::qGLExtensions::QueryFeatures(hdc); // calculate viewport sizes long maxw = screenwidth - 350; // assume 320x240 first long maxh = screenheight - 130 - 10; // text is fix splinevpsize = GLMin<long>(maxw, maxh); splinevpsize -= (splinevpsize % 10); surfvpwidth = screenwidth - splinevpsize - 30; surfvpheight = (surfvpwidth * 3) / 4; if( !Quadron::qGLExtensions::ARB_geometry_shader4 ) return false; hascompute = Quadron::qGLExtensions::ARB_compute_shader; #ifdef _DEBUG if( Quadron::qGLExtensions::ARB_debug_output ) { glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); glDebugMessageCallback(ReportGLError, 0); } #endif glClearColor(0.0f, 0.125f, 0.3f, 1.0f); glClearDepth(1.0); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); // create grid & control poly if( !GLCreateMesh(44 + numcontrolvertices, numcontrolindices, GLMESH_DYNAMIC, decl, &supportlines) ) { MYERROR("Could not create mesh"); return false; } supportlines->LockVertexBuffer(0, 0, GLLOCK_DISCARD, (void**)&vdata); supportlines->LockIndexBuffer(0, 0, GLLOCK_DISCARD, (void**)&idata); // grid points for( GLuint i = 0; i < 22; i += 2 ) { vdata[i][0] = vdata[i + 1][0] = (float)(i / 2); vdata[i][2] = vdata[i + 1][2] = 0; vdata[i][3] = vdata[i + 1][3] = 1; vdata[i][1] = 0; vdata[i + 1][1] = 10; vdata[i + 22][1] = vdata[i + 23][1] = (float)(i / 2); vdata[i + 22][2] = vdata[i + 23][2] = 0; vdata[i + 22][3] = vdata[i + 23][3] = 1; vdata[i + 22][0] = 0; vdata[i + 23][0] = 10; } // curve indices for( GLuint i = 0; i < numcontrolindices; i += 2 ) { idata[i] = 44 + i / 2; idata[i + 1] = 44 + i / 2 + 1; } supportlines->UnlockIndexBuffer(); supportlines->UnlockVertexBuffer(); OpenGLAttributeRange table[] = { { GLPT_LINELIST, 0, 0, 0, 0, 44 }, { GLPT_LINELIST, 1, 0, numcontrolindices, 44, numcontrolvertices } }; supportlines->SetAttributeTable(table, 2); // create spline mesh if( !GLCreateMesh(maxsplinevertices, maxsplineindices, GLMESH_32BIT, decl, &curve) ) { MYERROR("Could not create curve"); return false; } OpenGLAttributeRange* subset0 = curve->GetAttributeTable(); subset0->PrimitiveType = GLPT_LINELIST; subset0->IndexCount = 0; // create surface if( !GLCreateMesh(maxsurfacevertices, maxsurfaceindices, GLMESH_32BIT, decl2, &surface) ) { MYERROR("Could not create surface"); return false; } // load effects if( !GLCreateEffectFromFile("../media/shadersGL/color.vert", "../media/shadersGL/renderpoints.geom", "../media/shadersGL/color.frag", &renderpoints) ) { MYERROR("Could not load point renderer shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/color.vert", "../media/shadersGL/renderlines.geom", "../media/shadersGL/color.frag", &renderlines) ) { MYERROR("Could not load line renderer shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/rendersurface.vert", 0, "../media/shadersGL/rendersurface.frag", &rendersurface) ) { MYERROR("Could not load surface renderer shader"); return false; } if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/basic2D.frag", &basic2D) ) { MYERROR("Could not load basic 2D shader"); return false; } if( hascompute ) { if( !GLCreateComputeProgramFromFile("../media/shadersGL/tessellatecurve.comp", &tessellatecurve) ) { MYERROR("Could not load compute shader"); return false; } if( !GLCreateComputeProgramFromFile("../media/shadersGL/tessellatesurface.comp", &tessellatesurface) ) { MYERROR("Could not load compute shader"); return false; } } screenquad = new OpenGLScreenQuad(); // tessellate for the first time ChangeCurve(0); Tessellate(); // text GLCreateTexture(800, 130, 1, GLFMT_A8R8G8B8, &text1); UpdateText(); float angles[2] = { M_PI / 2, 0.5f }; cameraangle = angles; return true; }