/** * @brief Calculates transformation matrix for the model and its tags * @note The transformation matrix is only calculated once */ static float* R_CalcTransform (entity_t* e) { transform_t* t; float* mp; float mt[16], mc[16]; /* check if this entity is already transformed */ t = &e->transform; if (t->processing) Com_Error(ERR_DROP, "Ring in entity transformations!"); if (t->done) return t->matrix; /* process this matrix */ t->processing = true; mp = nullptr; /* do parent object transformations first */ if (e->tagent) { /* tag transformation */ const model_t* model = e->tagent->model; const mAliasTagOrientation_t* current = nullptr; const mAliasTagOrientation_t* old = nullptr; const animState_t* as = &e->tagent->as; R_GetTags(model, e->tagname, as->frame, as->oldframe, ¤t, &old); if (current != nullptr && old != nullptr) { float interpolated[16]; /* parent transformation */ mp = R_CalcTransform(e->tagent); /* do interpolation */ R_InterpolateTransform(as->backlerp, model->alias.num_frames, current, old, interpolated); /* transform */ GLMatrixMultiply(mp, interpolated, mt); mp = mt; } } GLMatrixAssemble(e->origin, e->angles, mc); /* combine transformations */ if (mp) GLMatrixMultiply(mp, mc, t->matrix); else memcpy(t->matrix, mc, sizeof(float) * 16); /* matrix elements 12..14 contain (forward) translation vector, which is also the origin of model after transform */ e->distanceFromViewOrigin = VectorDist(&t->matrix[12], refdef.viewOrigin); /* we're done */ t->done = true; t->processing = false; return t->matrix; }
void Render(float alpha, float elapsedtime) { static float time = 0; float lightpos[4] = { 6, 3, 10, 1 }; float eye[3] = { 0, 0, 3 }; float look[3] = { 0, 0, 0 }; float up[3] = { 0, 1, 0 }; float view[16]; float proj[16]; float world[16]; float viewproj[16]; float tmp1[16]; float tmp2[16]; glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); GLMatrixLookAtRH(view, eye, look, up); GLMatrixPerspectiveFovRH(proj, (60.0f * 3.14159f) / 180.f, (float)screenwidth / (float)screenheight, 0.1f, 100.0f); GLMatrixMultiply(viewproj, view, proj); //calculate world matrix GLMatrixIdentity(tmp2); tmp2[12] = -0.108f; // offset with bb center tmp2[13] = -0.7875f; // offset with bb center GLMatrixRotationAxis(tmp1, fmodf(time * 20.0f, 360.0f) * (3.14152f / 180.0f), 1, 0, 0); GLMatrixMultiply(world, tmp2, tmp1); GLMatrixRotationAxis(tmp2, fmodf(time * 20.0f, 360.0f) * (3.14152f / 180.0f), 0, 1, 0); GLMatrixMultiply(world, world, tmp2); // render time += elapsedtime; glUseProgram(program); glUniform4fv(uniform_eyePos, 1, eye); glUniform4fv(uniform_lightPos, 1, lightpos); glUniformMatrix4fv(uniform_matWorld, 1, false, world); glUniformMatrix4fv(uniform_matViewProj, 1, false, viewproj); { mesh->DrawSubset(0); } glUseProgram(0); // check errors GLenum err = glGetError(); if( err != GL_NO_ERROR ) std::cout << "Error\n"; SwapBuffers(hdc); }
void RenderScene(OpenGLEffect* effect) { float world[16]; float worldinv[16]; float tmp[16]; GLMatrixIdentity(world); for( int i = 0; i < numobjects; ++i ) { const SceneObject& obj = objects[i]; 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); GLMatrixInverse(worldinv, world); effect->SetMatrix("matWorld", world); effect->SetMatrix("matWorldInv", worldinv); if( obj.type == 0 ) { float uv[] = { 2, 2, 0, 1 }; effect->SetVector("uv", uv); effect->CommitChanges(); glBindTexture(GL_TEXTURE_2D, texture1); box->DrawSubset(0); } else if( obj.type == 1 ) { float uv[] = { 1, 1, 0, 1 }; effect->SetVector("uv", uv); effect->CommitChanges(); glBindTexture(GL_TEXTURE_2D, texture2); teapot->DrawSubset(0); } } glBindTexture(GL_TEXTURE_2D, 0); }
/** * @brief Calculates the muzzle for the current weapon the actor is shooting with * @param[in] actor The actor that is shooting. Might not be @c nullptr * @param[out] muzzle The muzzle vector to spawn the particle at. Might not be @c nullptr. This is not * modified if there is no tag for the muzzle found for the weapon or item the actor has * in the hand (also see the given shoot type) * @param[in] shootType The shoot type to determine which tag of the actor should be used * to resolve the world coordinates. Also used to determine which item (or better which hand) * should be used to resolve the actor's item. */ static void CL_ActorGetMuzzle (const le_t* actor, vec3_t muzzle, shoot_types_t shootType) { if (actor == nullptr) return; const Item* weapon; const char* tag; if (IS_SHOT_RIGHT(shootType)) { tag = "tag_rweapon"; weapon = actor->getRightHandItem(); } else { tag = "tag_lweapon"; weapon = actor->getLeftHandItem(); } if (!weapon || !weapon->def()) return; const objDef_t* od = weapon->def(); const model_t* model = cls.modelPool[od->idx]; if (!model) Com_Error(ERR_DROP, "Model for item %s is not precached", od->id); /* not every weapon has a muzzle tag assigned */ if (R_GetTagIndexByName(model, "tag_muzzle") == -1) return; float modifiedMatrix[16]; if (!R_GetTagMatrix(actor->model1, tag, actor->as.frame, modifiedMatrix)) Com_Error(ERR_DROP, "Could not find tag %s for actor model %s", tag, actor->model1->name); float mc[16]; GLMatrixAssemble(actor->origin, actor->angles, mc); float matrix[16]; GLMatrixMultiply(mc, modifiedMatrix, matrix); R_GetTagMatrix(model, "tag_muzzle", 0, modifiedMatrix); GLMatrixMultiply(matrix, modifiedMatrix, mc); muzzle[0] = mc[12]; muzzle[1] = mc[13]; muzzle[2] = mc[14]; }
void FPSCamera::GetViewVectors(float forward[3], float right[3], float up[3]) { float yaw[16]; float pitch[16]; // TODO: rollpitchyaw GLMatrixRotationAxis(yaw, anglecurve.curr[0], 0, 1, 0); GLMatrixRotationAxis(pitch, anglecurve.curr[1], 1, 0, 0); GLMatrixMultiply(view, yaw, pitch); GLVec3Set(forward, -view[2], -view[6], -view[10]); GLVec3Set(right, view[0], view[4], view[8]); GLVec3Set(up, view[1], view[5], view[9]); }
void FPSCamera::Animate(float alpha) { anglecurve.smooth(smoothedangles, alpha); body->GetInterpolatedPosition(position, alpha); position[1] += (1.8f - CAMERA_RADIUS); // recalculate view matrix float yaw[16]; float pitch[16]; // TODO: rollpitchyaw GLMatrixRotationAxis(yaw, smoothedangles[0], 0, 1, 0); GLMatrixRotationAxis(pitch, smoothedangles[1], 1, 0, 0); GLMatrixMultiply(view, yaw, pitch); view[12] = -(position[0] * view[0] + position[1] * view[4] + position[2] * view[8]); view[13] = -(position[0] * view[1] + position[1] * view[5] + position[2] * view[9]); view[14] = -(position[0] * view[2] + position[1] * view[6] + position[2] * view[10]); }
/* FUNCTION: GLCreateModelViewMatrix ARGUMENTS: m destination matrix x,y,z position yaw compass direction, 0-north, 90-east, 180-south, 270-west pitch azimuth, -90 down, 0 forwad, 90 up roll rotation around forward axis RETURN: n/a DESCRIPTION: Position camera */ void GLCreateModelViewMatrix(float *m, float x, float y, float z, float yaw, float pitch, float roll) { // same as gluLookAt Quaternion q, qDir, qAzim; qAzim.GenerateLocalRotation(pitch + 90.0f, -1.0f, 0.0f, 0.0f); qDir.GenerateLocalRotation(yaw, 0.0f, 0.0f, 1.0f); q = qAzim * qDir; if (roll != 0) { Quaternion qTilt; qTilt.GenerateLocalRotation(roll, 0, 0, 1); q = qTilt * q; } q.CreateRotatedQuaternion(m); // move camera float mov[16]; GLCreateIdentityMatrix(mov); mov[12] = -x; mov[13] = -y; mov[14] = -z; GLMatrixMultiply(m, m, mov); }
bool InitScene() { SetWindowText(hwnd, TITLE); Quadron::qGLExtensions::QueryFeatures(hdc); if( !Quadron::qGLExtensions::ARB_shader_storage_buffer_object ) return false; #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); //glClearColor(1, 1, 1, 1); glClearDepth(1.0); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); screenquad = new OpenGLScreenQuad(); // load objects if( !GLCreateMeshFromQM("../media/meshes/cube.qm", &box) ) { MYERROR("Could not load box"); return false; } if( !GLCreateMeshFromQM("../media/meshes/dragon.qm", &dragon) ) { MYERROR("Could not load dragon"); return false; } if( !GLCreateMeshFromQM("../media/meshes/happy1.qm", &buddha) ) { MYERROR("Could not load buddha"); return false; } // create texture glGenTextures(1, &white); glBindTexture(GL_TEXTURE_2D, white); { unsigned int wondercolor = 0xffffffff; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &wondercolor); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } // create buffers size_t headsize = 16; // start, count, pad, pad size_t nodesize = 16; // color, depth, next, pad size_t numlists = screenwidth * screenheight; glGenBuffers(1, &headbuffer); glGenBuffers(1, &nodebuffer); glGenBuffers(1, &counterbuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, headbuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, numlists * headsize, 0, GL_STATIC_DRAW); glBindBuffer(GL_SHADER_STORAGE_BUFFER, nodebuffer); glBufferData(GL_SHADER_STORAGE_BUFFER, numlists * 4 * nodesize, 0, GL_STATIC_DRAW); // 120 MB @ 1080p 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); // 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 = dragon->GetBoundingBox(); else if( obj.type == 2 ) tmpbox = buddha->GetBoundingBox(); tmpbox.TransformAxisAligned(world); scenebox.Add(tmpbox.Min); scenebox.Add(tmpbox.Max); } // head pointer initializer if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/initheadpointers.frag", &init) ) { MYERROR("Could not load initializer shader"); return false; } // renderer shader if( !GLCreateEffectFromFile("../media/shadersGL/basic2D.vert", 0, "../media/shadersGL/renderfragments.frag", &render) ) { MYERROR("Could not load rendering shader"); return false; } // fragment collector shader if( !GLCreateEffectFromFile("../media/shadersGL/collectfragments.vert", 0, "../media/shadersGL/collectfragments.frag", &collect) ) { MYERROR("Could not load collector shader"); return false; } float angles[2] = { 0.25f, -0.7f }; cameraangle = angles; return true; }
void Render(float alpha, float elapsedtime) { float world[16]; float tmp[16]; float view[16]; float proj[16]; float viewproj[16]; float eye[3] = { 0, 0.3f, 8 }; float look[3] = { 0, 0.3f, 0 }; float up[3] = { 0, 1, 0 }; float clipplanes[2]; float orient[2]; cameraangle.smooth(orient, alpha); GLMatrixRotationAxis(view, orient[1], 1, 0, 0); GLMatrixRotationAxis(tmp, orient[0], 0, 1, 0); GLMatrixMultiply(view, view, tmp); GLVec3Transform(eye, eye, view); GLFitToBox(clipplanes[0], clipplanes[1], eye, look, scenebox); GLMatrixPerspectiveFovRH(proj, (60.0f * 3.14159f) / 180.f, (float)screenwidth / (float)screenheight, clipplanes[0], clipplanes[1]); GLMatrixLookAtRH(view, eye, look, up); GLMatrixMultiply(viewproj, view, proj); // STEP 1: initialize header pointer buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDisable(GL_DEPTH_TEST); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, headbuffer); init->SetInt("screenWidth", screenwidth); init->Begin(); { screenquad->Draw(); } init->End(); // STEP 2: collect transparent fragments into lists glBindTexture(GL_TEXTURE_2D, white); glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counterbuffer); GLuint* counter = (GLuint*)glMapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_WRITE_ONLY); *counter = 0; glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER); glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, nodebuffer); glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counterbuffer); collect->SetMatrix("matView", view); collect->SetMatrix("matProj", proj); collect->SetInt("screenWidth", screenwidth); collect->Begin(); { 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); collect->SetMatrix("matWorld", world); collect->SetVector("matAmbient", &obj.color.r); collect->CommitChanges(); if( obj.type == 0 ) box->DrawSubset(0); else if( obj.type == 1 ) dragon->DrawSubset(0); else if( obj.type == 2 ) buddha->DrawSubset(0); } } collect->End(); glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0); // STEP 3: render glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_SRC_ALPHA); render->SetInt("screenWidth", screenwidth); render->Begin(); { screenquad->Draw(); } render->End(); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); #ifdef _DEBUG // check errors GLenum err = glGetError(); if( err != GL_NO_ERROR ) std::cout << "Error\n"; #endif SwapBuffers(hdc); mousedx = mousedy = 0; }
void Render(float alpha, float elapsedtime) { float tmp[16]; float texmat[16]; float view[16]; float viewinv[16]; float proj[16]; float viewproj[16]; float lightview[16]; float lightproj[16]; float lightviewproj[16]; float globalambient[4] = { 0.01f, 0.01f, 0.01f, 1.0f }; float moonlight[] = { -0.25f, 0.65f, -1, 0 }; float mooncolor[] = { 0.6f, 0.6f, 1, 1 }; float eye[3] = { 0, 0, 8 }; float look[3] = { 0, 0, 0 }; float up[3] = { 0, 1, 0 }; float screensize[2] = { (float)screenwidth, (float)screenheight }; float lightclip[2]; float clipplanes[2]; float orient[2]; // setup camera cameraangle.smooth(orient, alpha); GLMatrixRotationAxis(view, orient[1], 1, 0, 0); GLMatrixRotationAxis(tmp, orient[0], 0, 1, 0); GLMatrixMultiply(view, view, tmp); GLVec3Transform(eye, eye, view); GLFitToBox(clipplanes[0], clipplanes[1], eye, look, scenebox); GLMatrixPerspectiveFovRH(proj, (60.0f * 3.14159f) / 180.f, (float)screenwidth / (float)screenheight, clipplanes[0], clipplanes[1]); GLMatrixLookAtRH(view, eye, look, up); GLMatrixMultiply(viewproj, view, proj); // setup moonlight GLMatrixInverse(viewinv, view); GLVec3Transform(moonlight, moonlight, viewinv); GLVec3Normalize(moonlight, moonlight); // should be that value in view space (background is fix) // but let y stay in world space, so we see shadow moonlight[1] = 0.65f; GLMatrixViewVector(lightview, moonlight); GLFitToBox(lightproj, lightclip, lightview, scenebox); GLMatrixMultiply(lightviewproj, lightview, lightproj); // render shadow map glClearColor(0, 0, 0, 1); varianceshadow->SetMatrix("matViewProj", lightviewproj); varianceshadow->SetVector("clipPlanes", lightclip); shadowmap->Set(); { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); varianceshadow->Begin(); { RenderScene(varianceshadow); } varianceshadow->End(); } shadowmap->Unset(); // blur it float texelsize[] = { 1.0f / SHADOWMAP_SIZE, 1.0f / SHADOWMAP_SIZE }; glDepthMask(GL_FALSE); glBindTexture(GL_TEXTURE_2D, shadowmap->GetColorAttachment(0)); boxblur3x3->SetVector("texelSize", texelsize); blurredshadow->Set(); { boxblur3x3->Begin(); { screenquad->Draw(); } boxblur3x3->End(); } blurredshadow->Unset(); glDepthMask(GL_TRUE); // STEP 1: z pass ambient->SetMatrix("matViewProj", viewproj); ambient->SetVector("matAmbient", globalambient); framebuffer->Set(); { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // draw background first glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glBindTexture(GL_TEXTURE_2D, texture3); float scaledx = 1360.0f * (screenheight / 768.0f); float scale = screenwidth / scaledx; GLMatrixTranslation(tmp, -0.5f, 0, 0); GLMatrixScaling(texmat, scale, 1, 1); GLMatrixMultiply(texmat, tmp, texmat); GLMatrixTranslation(tmp, 0.5f, 0, 0); GLMatrixMultiply(texmat, texmat, tmp); GLMatrixRotationAxis(tmp, M_PI, 0, 0, 1); GLMatrixMultiply(texmat, texmat, tmp); basic2D->SetMatrix("matTexture", texmat); basic2D->Begin(); { screenquad->Draw(); } basic2D->End(); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); // then fill zbuffer ambient->Begin(); { RenderScene(ambient); } ambient->End(); } framebuffer->Unset(); // STEP 2: cull lights if( lightcull && timeout > DELAY ) { lightcull->SetFloat("alpha", alpha); lightcull->SetVector("clipPlanes", clipplanes); lightcull->SetVector("screenSize", screensize); lightcull->SetMatrix("matProj", proj); lightcull->SetMatrix("matView", view); lightcull->SetMatrix("matViewProj", viewproj); glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counterbuffer); GLuint* counter = (GLuint*)glMapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_WRITE_ONLY); *counter = 0; glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, headbuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, nodebuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, lightbuffer); glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counterbuffer); glBindTexture(GL_TEXTURE_2D, framebuffer->GetDepthAttachment()); lightcull->Begin(); { glDispatchCompute(workgroupsx, workgroupsy, 1); } lightcull->End(); glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0); glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); } // STEP 3: add some moonlight with shadow glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glDepthMask(GL_FALSE); framebuffer->Set(); shadowedlight->SetMatrix("matViewProj", viewproj); shadowedlight->SetMatrix("lightViewProj", lightviewproj); shadowedlight->SetVector("eyePos", eye); shadowedlight->SetVector("lightPos", moonlight); shadowedlight->SetVector("lightColor", mooncolor); shadowedlight->SetVector("clipPlanes", lightclip); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, blurredshadow->GetColorAttachment(0)); glActiveTexture(GL_TEXTURE0); shadowedlight->Begin(); { RenderScene(shadowedlight); } shadowedlight->End(); // STEP 4: accumulate lighting if( lightaccum && timeout > DELAY ) { lightaccum->SetMatrix("matViewProj", viewproj); lightaccum->SetVector("eyePos", eye); lightaccum->SetFloat("alpha", alpha); lightaccum->SetInt("numTilesX", workgroupsx); lightaccum->Begin(); { RenderScene(lightaccum); } lightaccum->End(); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0); } framebuffer->Unset(); glDisable(GL_BLEND); glDepthMask(GL_TRUE); // STEP 4: gamma correct glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, framebuffer->GetColorAttachment(0)); gammacorrect->Begin(); { screenquad->Draw(); } gammacorrect->End(); #ifdef _DEBUG // check errors GLenum err = glGetError(); if( err != GL_NO_ERROR ) std::cout << "Error\n"; #endif SwapBuffers(hdc); mousedx = mousedy = 0; }
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; }
void Render(float alpha, float elapsedtime) { float world[16]; float view[16]; float proj[16]; float eye[3]; basiccamera.Animate(alpha); basiccamera.GetViewMatrix(view); basiccamera.GetProjectionMatrix(proj); basiccamera.GetEyePosition(eye); GLVec4Set(uniformDTO.vsuniforms.lightPos, 6, 3, 10, 1); GLVec4Set(uniformDTO.vsuniforms.eyePos, eye[0], eye[1], eye[2], 1); GLMatrixMultiply(uniformDTO.vsuniforms.matViewProj, view, proj); GLMatrixScaling(uniformDTO.vsuniforms.matWorld, OBJECT_SCALE, OBJECT_SCALE, OBJECT_SCALE); switch( rendermethod ) { case 1: GLVec4Set(uniformDTO.fsuniforms.color, 1, 0, 0, 1); break; case 2: GLVec4Set(uniformDTO.fsuniforms.color, 1, 0.5f, 0, 1); break; case 3: GLVec4Set(uniformDTO.fsuniforms.color, 1, 1, 0, 1); break; case 4: GLVec4Set(uniformDTO.fsuniforms.color, 0, 0.75f, 0, 1); break; case 5: GLVec4Set(uniformDTO.fsuniforms.color, 0, 1, 0, 1); break; default: break; } // render pass OpenGLEffect* effect = ((rendermethod > 1) ? effect2 : effect1); GLsync sync = 0; if( rendermethod == 1 ) { effect1->SetMatrix("matViewProj", uniformDTO.vsuniforms.matViewProj); effect1->SetVector("lightPos", uniformDTO.vsuniforms.lightPos); effect1->SetVector("eyePos", uniformDTO.vsuniforms.eyePos); effect1->SetVector("color", uniformDTO.fsuniforms.color); } framebuffer->Set(); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); effect->Begin(); { for( int i = 0; i < GRID_SIZE; ++i ) { for( int j = 0; j < GRID_SIZE; ++j ) { for( int k = 0; k < GRID_SIZE; ++k ) { if( currentcopy >= UNIFORM_COPIES ) { if( rendermethod == 4 || rendermethod == 2 ) { sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); } else if( rendermethod == 5 ) { glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer3); glUnmapBuffer(GL_UNIFORM_BUFFER); persistentdata = (EffectUniformBlock*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, UNIFORM_COPIES * sizeof(EffectUniformBlock), GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT|GL_MAP_PERSISTENT_BIT|GL_MAP_COHERENT_BIT); assert(persistentdata != 0); glBindBuffer(GL_UNIFORM_BUFFER, 0); currentcopy = 0; } } uniformDTO.vsuniforms.matWorld[12] = GRID_SIZE * -0.5f + i; uniformDTO.vsuniforms.matWorld[13] = GRID_SIZE * -0.5f + j; uniformDTO.vsuniforms.matWorld[14] = GRID_SIZE * -0.5f + k; if( rendermethod == 1 ) { effect1->SetMatrix("matWorld", uniformDTO.vsuniforms.matWorld); effect1->CommitChanges(); } else { if( rendermethod == 2 ) { if( sync != 0 ) { glWaitSync(sync, 0, GL_TIMEOUT_IGNORED); glDeleteSync(sync); sync = 0; } glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer1); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(EffectUniformBlock), &uniformDTO); glBindBufferRange(GL_UNIFORM_BUFFER, 0, uniformbuffer1, 0, sizeof(EffectUniformBlock::VertexUniformData)); glBindBufferRange(GL_UNIFORM_BUFFER, 1, uniformbuffer1, offsetof(EffectUniformBlock, fsuniforms), sizeof(EffectUniformBlock::FragmentUniformData)); } else if( rendermethod == 3 ) { glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer1); void* data = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(EffectUniformBlock), GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT); { memcpy(data, &uniformDTO, sizeof(EffectUniformBlock)); } glUnmapBuffer(GL_UNIFORM_BUFFER); glBindBufferRange(GL_UNIFORM_BUFFER, 0, uniformbuffer1, 0, sizeof(EffectUniformBlock::VertexUniformData)); glBindBufferRange(GL_UNIFORM_BUFFER, 1, uniformbuffer1, offsetof(EffectUniformBlock, fsuniforms), sizeof(EffectUniformBlock::FragmentUniformData)); } else if( rendermethod == 4 ) { GLintptr baseoffset = currentcopy * sizeof(EffectUniformBlock); GLbitfield flags = GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT; if( sync != 0 ) { GLenum result = 0; GLbitfield waitflags = GL_SYNC_FLUSH_COMMANDS_BIT; do { result = glClientWaitSync(sync, waitflags, 500000); waitflags = 0; if( result == GL_WAIT_FAILED ) { std::cout << "glClientWaitSync() failed!\n"; break; } } while( result == GL_TIMEOUT_EXPIRED ); glDeleteSync(sync); sync = 0; currentcopy = 0; baseoffset = 0; } glBindBuffer(GL_UNIFORM_BUFFER, uniformbuffer2); void* data = glMapBufferRange(GL_UNIFORM_BUFFER, baseoffset, sizeof(EffectUniformBlock), flags); assert(data != 0); { memcpy(data, &uniformDTO, sizeof(EffectUniformBlock)); } glUnmapBuffer(GL_UNIFORM_BUFFER); glBindBufferRange(GL_UNIFORM_BUFFER, 0, uniformbuffer2, baseoffset, sizeof(EffectUniformBlock::VertexUniformData)); glBindBufferRange(GL_UNIFORM_BUFFER, 1, uniformbuffer2, baseoffset + offsetof(EffectUniformBlock, fsuniforms), sizeof(EffectUniformBlock::FragmentUniformData)); ++currentcopy; } else if( rendermethod == 5 ) { GLintptr baseoffset = currentcopy * sizeof(EffectUniformBlock); memcpy(persistentdata + currentcopy, &uniformDTO, sizeof(EffectUniformBlock)); glBindBufferRange(GL_UNIFORM_BUFFER, 0, uniformbuffer3, baseoffset, sizeof(EffectUniformBlock::VertexUniformData)); glBindBufferRange(GL_UNIFORM_BUFFER, 1, uniformbuffer3, baseoffset + offsetof(EffectUniformBlock, fsuniforms), sizeof(EffectUniformBlock::FragmentUniformData)); ++currentcopy; } } mesh->DrawSubset(0); } } } } effect->End(); framebuffer->Unset(); // present GLMatrixIdentity(world); glDisable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); basic2D->SetMatrix("matTexture", world); basic2D->Begin(); { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, framebuffer->GetColorAttachment(0)); screenquad->Draw(); } basic2D->End(); // render text glViewport(5, screenheight - 517, 512, 512); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float xzplane[4] = { 0, 1, 0, -0.5f }; GLMatrixReflect(world, xzplane); basic2D->SetMatrix("matTexture", world); basic2D->Begin(); { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, text1); screenquad->Draw(); } basic2D->End(); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); glViewport(0, 0, screenwidth, screenheight); // check errors GLenum err = glGetError(); if( err != GL_NO_ERROR ) std::cout << "Error\n"; SwapBuffers(hdc); }
void Render(float alpha, float elapsedtime) { static float time = 0; float world[16]; float view[16]; float proj[16]; float viewproj[16]; float viewinv[16]; float viewprojinv[16]; float eye[3]; float clip[4] = { 0, 0, 0, 0 }; orbitcamera.Animate(alpha); orbitcamera.GetViewMatrix(view); orbitcamera.GetProjectionMatrix(proj); orbitcamera.GetEyePosition(eye); clip[0] = orbitcamera.GetNearPlane(); clip[1] = orbitcamera.GetFarPlane(); GLMatrixInverse(viewinv, view); GLMatrixMultiply(viewproj, view, proj); GLMatrixInverse(viewprojinv, viewproj); glViewport(0, 0, screenwidth, screenheight); if( userefgtao ) { // using the reference spheres with GTAO refgbuffereffect->SetMatrix("matView", view); refgbuffereffect->SetMatrix("matViewInv", viewinv); refgbuffereffect->SetMatrix("matViewProjInv", viewprojinv); refgbuffereffect->SetVector("eyePos", eye); refgbuffereffect->SetVector("clipPlanes", clip); RenderReferenceWithGTAO(proj, clip, eye); } else { // using the reference spheres with path tracing RenderReferenceWithPathTracing(viewprojinv, eye, time); } if( drawtext ) { // render text glViewport(5, screenheight - 517, 512, 512); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float xzplane[4] = { 0, 1, 0, -0.5f }; GLMatrixReflect(world, xzplane); presenteffect->SetMatrix("matTexture", world); presenteffect->Begin(); { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, text1); screenquad->Draw(); } presenteffect->End(); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); GLMatrixIdentity(world); presenteffect->SetMatrix("matTexture", world); } time += elapsedtime; #ifdef _DEBUG GLenum err = glGetError(); if( err != GL_NO_ERROR ) std::cout << "Error\n"; #endif SwapBuffers(hdc); }
//************************************************************************************************************* void Render(float alpha, float elapsedtime) { OpenGLColor grcolor(0xffdddddd); OpenGLColor cvcolor(0xff7470ff); OpenGLColor splinecolor(0xff000000); OpenGLColor outsidecolor(0.75f, 0.75f, 0.8f, 1); OpenGLColor insidecolor(1, 0.66f, 0.066f, 1); float world[16]; float view[16]; float proj[16]; float viewproj[16]; float pointsize[2] = { 10.0f / screenwidth, 10.0f / screenheight }; float grthickness[2] = { 1.5f / screenwidth, 1.5f / screenheight }; float cvthickness[2] = { 2.0f / screenwidth, 2.0f / screenheight }; float spthickness[2] = { 3.0f / screenwidth, 3.0f / screenheight }; float spviewport[] = { 0, 0, (float)screenwidth, (float)screenheight }; float eye[3] = { 5, 4, 15 }; float look[3] = { 5, 4, 5 }; float up[3] = { 0, 1, 0 }; float lightdir[4] = { 0, 1, 0, 0 }; float fwd[3]; float orient[2]; // play with ortho matrix instead of viewport (line thickness remains constant) ConvertToSplineViewport(spviewport[0], spviewport[1]); ConvertToSplineViewport(spviewport[2], spviewport[3]); GLMatrixIdentity(world); GLMatrixOrthoRH(proj, spviewport[0], spviewport[2], spviewport[1], spviewport[3], -1, 1); glViewport(0, 0, screenwidth, screenheight); glClearColor(1, 1, 1, 1); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glDisable(GL_DEPTH_TEST); renderlines->SetMatrix("matViewProj", proj); renderlines->SetMatrix("matWorld", world); renderlines->SetVector("color", &grcolor.r); renderlines->SetVector("lineThickness", grthickness); renderlines->Begin(); { supportlines->DrawSubset(0); renderlines->SetVector("color", &cvcolor.r); renderlines->SetVector("lineThickness", cvthickness); renderlines->CommitChanges(); supportlines->DrawSubset(1); if( hascompute ) { renderlines->SetVector("lineThickness", spthickness); renderlines->SetVector("color", &splinecolor.r); renderlines->CommitChanges(); curve->DrawSubset(0); } } renderlines->End(); renderpoints->SetMatrix("matViewProj", proj); renderpoints->SetMatrix("matWorld", world); renderpoints->SetVector("color", &cvcolor.r); renderpoints->SetVector("pointSize", pointsize); renderpoints->Begin(); { glBindVertexArray(supportlines->GetVertexLayout()); glDrawArrays(GL_POINTS, 44, numcontrolvertices); } renderpoints->End(); // render surface in a smaller viewport if( !fullscreen ) { glEnable(GL_SCISSOR_TEST); glScissor(screenwidth - surfvpwidth - 10, screenheight - surfvpheight - 10, surfvpwidth, surfvpheight); } glClearColor(0.0f, 0.125f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); glEnable(GL_DEPTH_TEST); if( fullscreen ) glViewport(0, 0, screenwidth, screenheight); else glViewport(screenwidth - surfvpwidth - 10, screenheight - surfvpheight - 10, surfvpwidth, surfvpheight); cameraangle.smooth(orient, alpha); GLVec3Subtract(fwd, look, eye); GLMatrixRotationYawPitchRoll(view, orient[0], orient[1], 0); GLVec3Transform(fwd, fwd, view); GLVec3Subtract(eye, look, fwd); GLMatrixPerspectiveRH(proj, M_PI / 3, 4.0f / 3.0f, 0.1f, 50.0f); GLMatrixLookAtRH(view, eye, look, up); GLMatrixMultiply(viewproj, view, proj); if( wireframe ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDisable(GL_CULL_FACE); if( hascompute ) { rendersurface->SetMatrix("matViewProj", viewproj); rendersurface->SetMatrix("matWorld", world); rendersurface->SetMatrix("matWorldInv", world); // its id rendersurface->SetVector("lightDir", lightdir); rendersurface->SetVector("eyePos", eye); rendersurface->SetVector("outsideColor", &outsidecolor.r); rendersurface->SetVector("insideColor", &insidecolor.r); rendersurface->SetInt("isWireMode", wireframe); rendersurface->Begin(); { surface->DrawSubset(0); } rendersurface->End(); } glEnable(GL_CULL_FACE); if( wireframe ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // render text if( !fullscreen ) { glViewport(3, 0, 800, 130); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float xzplane[4] = { 0, 1, 0, -0.5f }; GLMatrixReflect(world, xzplane); basic2D->SetMatrix("matTexture", world); basic2D->SetInt("sampler0", 0); basic2D->Begin(); { glBindTexture(GL_TEXTURE_2D, text1); screenquad->Draw(); } basic2D->End(); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); } #ifdef _DEBUG // check errors GLenum err = glGetError(); if( err != GL_NO_ERROR ) std::cout << "Error\n"; #endif SwapBuffers(hdc); mousedx = mousedy = 0; }