void ChangeSize(int w, int h) { g_camera.ChangeViewportSize(w, h); }
int main(int argc, char **argv) { int width,height; Camera cam; int mousedx=0; int mousedy=0; int fps=0; int nrOfObjects=0; int nrOfLights=0; float tdropoff=0.0f; float topacity=0.0f; float tradius=0.0f; int nrOfPaths=0; int nrOfParticleSystems=0; float gr=0.0f; float gg=0.0f; float gb=0.0f; sf::Clock clock; //window options width=1280; height=720; sf::WindowSettings settings; settings.DepthBits = 24; settings.StencilBits = 8; settings.AntialiasingLevel = 1; sf::Window app; app.Create(sf::VideoMode(width, height, 32), "Saints Edit", sf::Style::Close|sf::Style::Resize, settings); app.UseVerticalSync(true); GLenum err = glewInit(); if (GLEW_OK != err) { cout<<"ERROR starting GLEW: "<< glewGetErrorString(err); } //Start renderer after glewinit,GLSPprog needs it (could add init method for global renderer) Renderer rend; GUI gui; gui.init(); gui.drawSplashScreen(); app.Display(); //sets up the terrain Terrain terrain(0); PathHandler ph; LightHandler lh; ParticleHandler particleHandler; particleHandler.init(); lh.init(); ph.init(); terrain.setRadius(gui.getSliderRadius()); terrain.setOpacity(gui.getSliderOpacity()); gui.setSurfaceTexHandles(terrain.getSurfaceTexHandles()); //the gui needs the textures for browsing gui.setTerrainInfo(terrain.getTerrInfo()); rend.updateProjMatrix(width,height); rend.updateViewMatrix(cam.getViewMatrix()); terrain.updateProjMatrix(width,height); terrain.updateViewMatrix(cam.getViewMatrix()); ph.updateProjectionMatrix(width,height); ph.updateViewMatrix(cam.getViewMatrix()); glViewport(0,0,width,height); MeshHandler mh("./models/"); for(int i=0; i<mh.getNrOfMeshes(); i++) { Model tmp; tmp.setMesh(mh.getMeshInfo(i)); tmp.setBoundingBox(mh.getBoundingBox(i)); tmp.setMeshName(mh.getMeshName(i)); tmp.setType(mh.getMeshType(i)); gui.addDisplayModel(tmp); } sf::Event event; Model m; TwInit(TW_OPENGL_CORE,NULL); TwWindowSize(width,height); TwBar *myBar; myBar = TwNewBar("info"); TwDefine(" info position='25 40' size='240 320' help='Information about the map etc.' refresh=0.1 "); TwAddButton(myBar, "gi", NULL, NULL, " label='General info' "); TwAddVarRO(myBar,"fps ", TW_TYPE_INT32, &fps,NULL); TwAddVarRO(myBar,"# Models ", TW_TYPE_INT32, &nrOfObjects,NULL); TwAddVarRO(myBar,"# Lights ", TW_TYPE_INT32, &nrOfLights,NULL); TwAddVarRO(myBar,"# Particlesystems ", TW_TYPE_INT32, &nrOfParticleSystems,NULL); TwAddVarRO(myBar,"# Paths ", TW_TYPE_INT32, &nrOfPaths,NULL); TwAddSeparator(myBar, "sep1", NULL); TwAddButton(myBar, "di", NULL, NULL, " label='Brush info' "); TwAddVarRO(myBar,"Radius", TW_TYPE_FLOAT, &tradius,NULL); TwAddVarRO(myBar,"Dropoff", TW_TYPE_FLOAT, &tdropoff,NULL); TwAddVarRO(myBar,"Opacity", TW_TYPE_FLOAT, &topacity,NULL); TwAddSeparator(myBar, "sep2", NULL); TwAddButton(myBar, "ci", NULL, NULL, " label='Color selected' "); TwAddVarRO(myBar,"Red", TW_TYPE_FLOAT, &gr,NULL); TwAddVarRO(myBar,"Green", TW_TYPE_FLOAT, &gg,NULL); TwAddVarRO(myBar,"Blue", TW_TYPE_FLOAT, &gb,NULL); while (app.IsOpened()) { float normalisedx = 0; float normalisedy = 0; nrOfObjects=rend.getNrOfModels(); nrOfLights=lh.getNrOfLights(); tradius=gui.getSliderRadius(); tdropoff=gui.getSliderDropoff(); topacity=gui.getSliderOpacity(); nrOfParticleSystems=particleHandler.getNrOfParticleSystems(); nrOfPaths=ph.getNrOfPaths(); gr=gui.getNormalizedColor().x; gg=gui.getNormalizedColor().y; gb=gui.getNormalizedColor().z; getNormalizedXY(app.GetInput().GetMouseX(), app.GetInput().GetMouseY(),width,height,normalisedx, normalisedy); //events int handled; while(app.GetEvent(event)) { handled = TwEventSFML(&event, 1,6); if(!handled) { if(event.Type==sf::Event::Closed) { app.Close(); } if((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Escape)) { app.Close(); } if(event.Type==sf::Event::MouseMoved) { if(gui.getState()==GUIstate::PAINT) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); terrain.setWorldXY(cam.getPos(),ray); } } if(event.Type == sf::Event::Resized) { height = app.GetHeight(); width = app.GetWidth(); glViewport(0,0,width,height); rend.updateProjMatrix(width,height); terrain.updateProjMatrix(width,height); ph.updateProjectionMatrix(width,height); } if(event.Type == sf::Event::MouseWheelMoved) { if(event.MouseWheel.Delta>0) cam.zoomIn(event.MouseWheel.Delta*2); else cam.zoomOut(-event.MouseWheel.Delta*2); rend.updateViewMatrix(cam.getViewMatrix()); terrain.updateViewMatrix(cam.getViewMatrix()); ph.updateViewMatrix(cam.getViewMatrix()); } if(event.Type == sf::Event::MouseButtonPressed) { if(event.MouseButton.Button==sf::Mouse::Right) { gui.showMenu(true); gui.setRightClickXY(normalisedx,normalisedy); particleHandler.unselectAllParticleModels(); } } if(event.Type == sf::Event::MouseButtonPressed) { if(event.MouseButton.Button==sf::Mouse::Left) { gui.setLeftClick(normalisedx,normalisedy); terrain.setActiveTex(gui.getActiveTex()); if(gui.checkDialogAnswer()=="GRID") { terrain.showHideGridMap(); gui.resetDialogAns(); } if(!gui.isSaveMapDialogUp()&&!gui.isLoadMapDialogUp()&&!gui.isNewMapDialogUp()) { if(gui.getState()==GUIstate::PARTICLE) { if(gui.isInDrawWindow(normalisedx,normalisedy)) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); float x=-1; float z=1; terrain.rayIntersectTerrain(cam.getPos(), ray, x, z); if(gui.isPlacingParticleSystems()) { if(x>0) { particleHandler.unselectAllParticleModels(); Particle p; p=gui.getActiveParticleModel(); p.setPos(vec3(x,gui.getActiveParticleModel().getPos().y,-z)); particleHandler.addParticleModel(p); gui.setActiveParticleModel(particleHandler.getSelectedParticle()); } } else { particleHandler.selectParticles(normalisedx,normalisedy,cam.getPos(),rend.getProjMatrix(),cam.getViewMatrix()); gui.setActiveParticleModel(particleHandler.getSelectedParticle()); } } } if(gui.getState()==GUIstate::ROAD) { if(gui.checkDialogAnswer()=="RS") { terrain.removeSelectedSurfaces(); gui.resetDialogAns(); } } if(gui.getState()==GUIstate::NONE) { if(gui.checkDialogAnswer()=="DEL") { vector<Model> rm = rend.removeSelectedModels(); lh.removeLightsBoundToModels(rm); vector<Model> tm =rend.getModels(); terrain.recalcGridAroundModel(rm,tm); terrain.removeSelectedSurfaces(); gui.resetDialogAns(); } } if(gui.getState()==GUIstate::PARTICLE) { if(gui.checkDialogAnswer()=="DEL") { particleHandler.removeSelectedParticles(); gui.resetDialogAns(); } } if(gui.getState()==GUIstate::PATH) { if(gui.checkDialogAnswer()=="DEL") { ph.removeSelectedPaths(); gui.resetDialogAns(); } if(gui.checkDialogAnswer()=="CRP") { ph.addPath(); gui.resetDialogAns(); } if(gui.isInDrawWindow(normalisedx,normalisedy)) { if(gui.isSelectingRoad()) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); float x=-1; float z=1; terrain.rayIntersectTerrain(cam.getPos(), ray, x, z); if(x>0) { ph.addFlagToCurrentPath(vec3(x,0,-z)); } } else { ph.selectPaths(normalisedx,normalisedy,cam.getPos()); } } } if(gui.getState()==GUIstate::MODEL||gui.getState()==GUIstate::NONE) { if(gui.getState()==GUIstate::MODEL) { if(gui.isInDrawWindow(normalisedx,normalisedy)) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); float x=-1; float z=1; terrain.rayIntersectTerrain(cam.getPos(), ray, x, z); if(x>0) { if(m.getType()=="light") { m.bindId(bindCounter); vec3 lpos = m.getPos(); lpos.y+=1; Light tmpLight; tmpLight.setColor(gui.getNormalizedColor()); tmpLight.setPos(lpos); tmpLight.setRadius(gui.getSliderLightRadius()); tmpLight.bindId(bindCounter); tmpLight.setContrast(gui.getContrast()); tmpLight.setLightType(LightType::POINTLIGHTSHADOW); lh.addLight(tmpLight); bindCounter++; } rend.addModel(m); terrain.setWorldXY(cam.getPos(),ray); terrain.makeGridUnderModel(m); } } } if(gui.getState()==GUIstate::NONE) { if(gui.isInDrawWindow(normalisedx,normalisedy)) { rend.selectModel(normalisedx,normalisedy,cam.getPos()); } } } if(gui.getState()==GUIstate::ROAD) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); terrain.setWorldXY(cam.getPos(),ray); terrain.selectTexSurfaces(0.5,cam.getPos(),ray); } if(gui.getState()==GUIstate::LIGHT) { if(gui.isInDrawWindow(normalisedx,normalisedy)) { if(gui.isPlacingLightMode()) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); float x=-1; float z=1; terrain.rayIntersectTerrain(cam.getPos(), ray, x, z); if(x>0) { Light l = gui.getActiveLight(); lh.deselectAllLights(); l.setPos(vec3(x,l.getPos().y,-z)); lh.addLight(l); } } else { int lightPos=lh.selectLight(normalisedx,normalisedy,cam.getPos(),rend.getProjMatrix(),cam.getViewMatrix()); if(lightPos>=0) { Light tmpl = lh.getSelectedLight(); gui.setSliderLightRadius(tmpl.getRadius()); gui.setNormalizedColor(tmpl.getColor(),tmpl.getContrast()); gui.setActiveLightModel(tmpl); } } } if(gui.checkDialogAnswer()=="DEL") { lh.removeSelectedLights(); } } } if(gui.isSaveMapDialogUp()) { if(gui.checkDialogAnswer()=="svOK") { save(gui.getInputText(),terrain,rend,ph,lh,particleHandler); gui.hideSaveMapDialog(); } if(gui.checkDialogAnswer()=="svC") { gui.hideSaveMapDialog(); } } if(gui.isNewMapDialogUp()) { if(gui.checkDialogAnswer()=="nmCS") { terrain.createNewMap(0); rend.clear(); ph.clear(); lh.clear(); particleHandler.clear(); gui.hideNewMapDialog(); } if(gui.checkDialogAnswer()=="nmCM") { terrain.createNewMap(1); rend.clear(); ph.clear(); lh.clear(); particleHandler.clear(); gui.hideNewMapDialog(); } if(gui.checkDialogAnswer()=="nmCL") { terrain.createNewMap(2); rend.clear(); ph.clear(); lh.clear(); particleHandler.clear(); gui.hideNewMapDialog(); } if(gui.checkDialogAnswer()=="nmOK") { terrain.createNewMap(0); rend.clear(); ph.clear(); lh.clear(); particleHandler.clear(); gui.hideNewMapDialog(); } if(gui.checkDialogAnswer()=="nmC") { gui.hideNewMapDialog(); } } if(gui.isLoadMapDialogUp()) { if(gui.checkDialogAnswer()=="lmOK") { load(gui.getInputText(),terrain,rend,ph,lh,particleHandler,mh); gui.hideLoadMapDialog(); } if(gui.checkDialogAnswer()=="lmC") { gui.hideLoadMapDialog(); } } } } if(event.Type == sf::Event::MouseButtonReleased) { if(event.MouseButton.Button==sf::Mouse::Right) { gui.showMenu(false); rend.unselectAllModels(); } } //if the gui excpects text input if(gui.isInTextMode()) { if(event.Type == sf::Event::KeyPressed) { if(int(event.Key.Code)>=97&&event.Key.Code<=122) gui.addChar(char(event.Key.Code)); } if((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Key::Back)) { gui.removeChar(); } } } } //realtime input if(app.GetInput().IsMouseButtonDown(sf::Mouse::Left)) { if(!handled) { if(!gui.isSaveMapDialogUp()&&!gui.isLoadMapDialogUp()&&!gui.isNewMapDialogUp()) { if(gui.isInDrawWindow(normalisedx,normalisedy)) { if(gui.getState()==GUIstate::PAINT) { terrain.setTerState(TerrState::PAINT); terrain.paint(cam.getPos(),inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos())); } if(gui.getState()==GUIstate::ROAD) { terrain.setTerState(TerrState::DRAWSURFACE); vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); terrain.addSurface(cam.getPos(),ray, gui.getActiveSurfaceTexHandle()); } } else { gui.moveSliders(normalisedx,normalisedy); if(gui.getState()==GUIstate::PAINT) { terrain.setRadius(gui.getSliderRadius()); terrain.setOpacity(gui.getSliderOpacity()); terrain.setDropoff(gui.getSliderDropoff()); } if(gui.getState()==GUIstate::ROAD) { terrain.setRoadSpacing(gui.getRoadSliderSpacing()); terrain.setRoadScale(gui.getRoadSliderScale()); } if(gui.getState()==GUIstate::PARTICLE) { particleHandler.assignParticleNewParticle(gui.getActiveParticleModel()); } if(gui.getState()==GUIstate::LIGHT) lh.assignLightAnotherLight(gui.getActiveLight()); } } } } if(app.GetInput().IsMouseButtonDown(sf::Mouse::Right)) { gui.setMouseXY(normalisedx,normalisedy); terrain.deselectAllSurfaceTex(); lh.deselectAllLights(); } //if the user isnt in text mode, it should be able to move if(!gui.isInTextMode()) { if(app.GetInput().IsKeyDown(sf::Key::Delete)) { if(gui.getState()==GUIstate::MODEL||gui.getState()==GUIstate::NONE) { vector<Model> rm = rend.removeSelectedModels(); lh.removeLightsBoundToModels(rm); vector<Model> tm =rend.getModels(); terrain.recalcGridAroundModel(rm,tm); } if(gui.getState()==GUIstate::PATH) { ph.removeSelectedPaths(); } if(gui.getState()==GUIstate::PARTICLE) { particleHandler.removeSelectedParticles(); } if(gui.getState()==GUIstate::ROAD) { terrain.removeSelectedSurfaces(); } if(gui.getState()==GUIstate::LIGHT) { lh.removeSelectedLights(); } } if(gui.getState()==GUIstate::PAINT) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); terrain.setWorldXY(cam.getPos(),ray); } if(app.GetInput().IsKeyDown(sf::Key::W)) { cam.moveForeward(0.1); } if(app.GetInput().IsKeyDown(sf::Key::S)) { cam.moveBackward(0.1); } if(app.GetInput().IsKeyDown(sf::Key::A)) { cam.strafeLeft(0.1); } if(app.GetInput().IsKeyDown(sf::Key::D)) { cam.strafeRight(0.1); } rend.updateViewMatrix(cam.getViewMatrix()); terrain.updateViewMatrix(cam.getViewMatrix()); ph.updateViewMatrix(cam.getViewMatrix()); if(gui.getState()==GUIstate::MODEL) { if(app.GetInput().IsKeyDown(sf::Key::Q)) gui.rotateActiveModelLeft(1.0f); if(app.GetInput().IsKeyDown(sf::Key::E)) gui.rotateActiveModelRight(1.0f); if(app.GetInput().IsKeyDown(sf::Key::R)) gui.raiseActiveModel(0.01); if(app.GetInput().IsKeyDown(sf::Key::F)) gui.raiseActiveModel(-0.01); } } if(app.GetInput().IsMouseButtonDown(sf::Mouse::Middle)) { cam.rotateLeft(mousedx-app.GetInput().GetMouseX()); cam.rotateUp(mousedy-app.GetInput().GetMouseY()); rend.updateViewMatrix(cam.getViewMatrix()); terrain.updateViewMatrix(cam.getViewMatrix()); ph.updateViewMatrix(cam.getViewMatrix()); } if(app.GetInput().IsMouseButtonDown(sf::Mouse::Right)) { gui.showMenu(true); if(gui.getState()==GUIstate::PAINT) { terrain.showCircle(); } else terrain.hideCircle(); } //saves the position of the mouse, used for rotation mousedx=app.GetInput().GetMouseX(); mousedy=app.GetInput().GetMouseY(); glClearColor(0.75f, 0.87f, 0.85f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); terrain.draw(); rend.draw(); if(gui.getState()==GUIstate::PATH) { ph.drawPaths(); if(gui.isSelectingRoad()) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); float x=-1; float z=1; terrain.rayIntersectTerrain(cam.getPos(), ray, x, z); if(x>0) ph.drawFlag(vec3(x,0,-z)); } } if(gui.getState()==GUIstate::ROAD) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); terrain.drawSurface(cam.getPos(),ray, gui.getActiveSurfaceTexHandle(),app.GetInput().IsMouseButtonDown(sf::Mouse::Left)); } if(gui.getState()==GUIstate::LIGHT) { lh.drawLights(rend.getProjMatrix(),cam.getViewMatrix()); if(gui.isPlacingLightMode()) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); float x=-1; float z=1; terrain.rayIntersectTerrain(cam.getPos(), ray, x, z); if(x>0) { Light l = gui.getActiveLight(); l.setPos(vec3(x,l.getPos().y,-z)); //l.select(); lh.drawLight(rend.getProjMatrix(),cam.getViewMatrix(),l); } } } if(gui.getState()==GUIstate::MODEL &&gui.isInDrawWindow(normalisedx,normalisedy) ) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); float x=-1; float z=1; terrain.rayIntersectTerrain(cam.getPos(), ray, x, z); if(x>0) { m=gui.getActiveModel(); m.setPos(vec3(x,gui.getActiveModel().getPos().y,-z)); m.scaleXYZ(m.getScale()); m.rotateY(m.getRot().y); rend.drawModel(m); } } if(gui.getState()==GUIstate::PARTICLE) { particleHandler.drawParticleModels(rend.getProjMatrix(),cam.getViewMatrix()); if(gui.isPlacingParticleSystems()) { vec3 ray = inters.getClickRay(app.GetInput().GetMouseX(),app.GetInput().GetMouseY(),cam.getViewMatrix(),rend.getProjMatrix(),width,height,cam.getPos()); float x=-1; float z=1; terrain.rayIntersectTerrain(cam.getPos(), ray, x, z); if(x>0) { Particle p = gui.getActiveParticleModel(); p.setPos(vec3(x,gui.getActiveParticleModel().getPos().y,-z)); particleHandler.drawParticleModel(rend.getProjMatrix(),cam.getViewMatrix(),p); } } } gui.draw(); fps= 1.0f/clock.GetElapsedTime(); clock.Reset(); TwDraw(); app.Display(); } TwTerminate(); lh.free(); return EXIT_SUCCESS; }
void ModelViewer::Startup( void ) { m_RootSig.Reset(6, 2); m_RootSig.InitStaticSampler(0, SamplerAnisoWrapDesc, D3D12_SHADER_VISIBILITY_PIXEL); m_RootSig.InitStaticSampler(1, SamplerShadowDesc, D3D12_SHADER_VISIBILITY_PIXEL); m_RootSig[0].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_VERTEX); m_RootSig[1].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_PIXEL); #if USE_ROOT_BUFFER_SRV || USE_VERTEX_BUFFER m_RootSig[2].InitAsBufferSRV(0, D3D12_SHADER_VISIBILITY_VERTEX); #else m_RootSig[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1, D3D12_SHADER_VISIBILITY_VERTEX); #endif m_RootSig[3].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 6, D3D12_SHADER_VISIBILITY_PIXEL); m_RootSig[4].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 64, 3, D3D12_SHADER_VISIBILITY_PIXEL); m_RootSig[5].InitAsConstants(1, 1, D3D12_SHADER_VISIBILITY_VERTEX); #if USE_VERTEX_BUFFER m_RootSig.Finalize(D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); #else m_RootSig.Finalize(); #endif DXGI_FORMAT ColorFormat = g_SceneColorBuffer.GetFormat(); DXGI_FORMAT DepthFormat = g_SceneDepthBuffer.GetFormat(); DXGI_FORMAT ShadowFormat = g_ShadowBuffer.GetFormat(); #if USE_VERTEX_BUFFER D3D12_INPUT_ELEMENT_DESC vertElem[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "BITANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } }; #endif m_DepthPSO.SetRootSignature(m_RootSig); m_DepthPSO.SetRasterizerState(RasterizerDefault); m_DepthPSO.SetBlendState(BlendNoColorWrite); m_DepthPSO.SetDepthStencilState(DepthStateReadWrite); #if USE_VERTEX_BUFFER m_DepthPSO.SetInputLayout(_countof(vertElem), vertElem); #endif m_DepthPSO.SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE); m_DepthPSO.SetRenderTargetFormats(0, nullptr, DepthFormat); m_DepthPSO.SetVertexShader(g_pDepthViewerVS, sizeof(g_pDepthViewerVS)); m_DepthPSO.SetPixelShader(g_pDepthViewerPS, sizeof(g_pDepthViewerPS)); m_DepthPSO.Finalize(); m_ShadowPSO = m_DepthPSO; m_ShadowPSO.SetRasterizerState(RasterizerShadow); m_ShadowPSO.SetRenderTargetFormats(0, nullptr, g_ShadowBuffer.GetFormat()); m_ShadowPSO.Finalize(); m_ModelPSO = m_DepthPSO; m_ModelPSO.SetBlendState(BlendDisable); m_ModelPSO.SetDepthStencilState(DepthStateTestEqual); m_ModelPSO.SetRenderTargetFormats(1, &ColorFormat, DepthFormat); m_ModelPSO.SetVertexShader( g_pModelViewerVS, sizeof(g_pModelViewerVS) ); m_ModelPSO.SetPixelShader( g_pModelViewerPS, sizeof(g_pModelViewerPS) ); m_ModelPSO.Finalize(); m_ExtraTextures[0] = g_SSAOFullScreen.GetSRV(); m_ExtraTextures[1] = g_ShadowBuffer.GetSRV(); TextureManager::Initialize(L"Textures/"); ASSERT(m_Model.Load("Models/sponza.h3d"), "Failed to load model"); ASSERT(m_Model.m_Header.meshCount > 0, "Model contains no meshes"); CreateParticleEffects(); float modelRadius = Length(m_Model.m_Header.boundingBox.max - m_Model.m_Header.boundingBox.min) * .5f; const Vector3 eye = (m_Model.m_Header.boundingBox.min + m_Model.m_Header.boundingBox.max) * .5f + Vector3(modelRadius * .5f, 0.0f, 0.0f); m_Camera.SetEyeAtUp( eye, Vector3(kZero), Vector3(kYUnitVector) ); m_Camera.SetZRange( 1.0f, 10000.0f ); m_pCameraController = new CameraController(m_Camera, Vector3(kYUnitVector)); MotionBlur::Enable = true; TemporalAA::Enable = true; FXAA::Enable = true; PostEffects::EnableHDR = true; PostEffects::EnableAdaptation = true; PostEffects::AdaptationRate = 0.05f; PostEffects::TargetLuminance = 0.4f; PostEffects::MinExposure = 1.0f; PostEffects::MaxExposure = 8.0f; PostEffects::BloomThreshold = 1.0f; PostEffects::BloomStrength = 0.10f; }
void ModelViewer::Update( float deltaT ) { ScopedTimer _prof(L"Update State"); if (GameInput::IsFirstPressed(GameInput::kLShoulder)) DebugZoom.Decrement(); else if (GameInput::IsFirstPressed(GameInput::kRShoulder)) DebugZoom.Increment(); m_pCameraController->Update(deltaT); m_ViewProjMatrix = m_Camera.GetViewProjMatrix(); float costheta = cosf(m_SunOrientation); float sintheta = sinf(m_SunOrientation); float cosphi = cosf(m_SunInclination * 3.14159f * 0.5f); float sinphi = sinf(m_SunInclination * 3.14159f * 0.5f); m_SunDirection = Normalize(Vector3( costheta * cosphi, sinphi, sintheta * cosphi )); // We use viewport offsets to jitter our color samples from frame to frame (with TAA.) // D3D has a design quirk with fractional offsets such that the implicit scissor // region of a viewport is floor(TopLeftXY) and floor(TopLeftXY + WidthHeight), so // having a negative fractional top left, e.g. (-0.25, -0.25) would also shift the // BottomRight corner up by a whole integer. One solution is to pad your viewport // dimensions with an extra pixel. My solution is to only use positive fractional offsets, // but that means that the average sample position is +0.5, which I use when I disable // temporal AA. if (TemporalAA::Enable) { uint64_t FrameIndex = Graphics::GetFrameCount(); #if 1 // 2x super sampling with no feedback float SampleOffsets[2][2] = { { 0.25f, 0.25f }, { 0.75f, 0.75f }, }; const float* Offset = SampleOffsets[FrameIndex & 1]; #else // 4x super sampling via controlled feedback float SampleOffsets[4][2] = { { 0.125f, 0.625f }, { 0.375f, 0.125f }, { 0.875f, 0.375f }, { 0.625f, 0.875f } }; const float* Offset = SampleOffsets[FrameIndex & 3]; #endif m_MainViewport.TopLeftX = Offset[0]; m_MainViewport.TopLeftY = Offset[1]; } else { m_MainViewport.TopLeftX = 0.5f; m_MainViewport.TopLeftY = 0.5f; } m_MainViewport.Width = (float)g_SceneColorBuffer.GetWidth(); m_MainViewport.Height = (float)g_SceneColorBuffer.GetHeight(); m_MainViewport.MinDepth = 0.0f; m_MainViewport.MaxDepth = 1.0f; m_MainScissor.left = 0; m_MainScissor.top = 0; m_MainScissor.right = (LONG)g_SceneColorBuffer.GetWidth(); m_MainScissor.bottom = (LONG)g_SceneColorBuffer.GetHeight(); }
int main(int argc, char** argv) { if (!glfwInit()) // 初始化glfw库 { std::cout << "Error::GLFW could not initialize GLFW!" << std::endl; return -1; } // 开启OpenGL 3.3 core profile std::cout << "Start OpenGL core profile version 3.3" << std::endl; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); glfwWindowHint(GLFW_SAMPLES, 4); // 设置采样点个数 注意这里设置GLFW选项 不要写成了GL_SAMPLES // 创建窗口 GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo of anti-aliasing(press O on, F off)", NULL, NULL); if (!window) { std::cout << "Error::GLFW could not create winddow!" << std::endl; glfwTerminate(); std::system("pause"); return -1; } // 创建的窗口的context指定为当前context glfwMakeContextCurrent(window); // 注册窗口键盘事件回调函数 glfwSetKeyCallback(window, key_callback); // 注册鼠标事件回调函数 glfwSetCursorPosCallback(window, mouse_move_callback); // 注册鼠标滚轮事件回调函数 glfwSetScrollCallback(window, mouse_scroll_callback); // 鼠标捕获 停留在程序内 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); // 初始化GLEW 获取OpenGL函数 glewExperimental = GL_TRUE; // 让glew获取所有拓展函数 GLenum status = glewInit(); if (status != GLEW_OK) { std::cout << "Error::GLEW glew version:" << glewGetString(GLEW_VERSION) << " error string:" << glewGetErrorString(status) << std::endl; glfwTerminate(); std::system("pause"); return -1; } // 设置视口参数 glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); //Section1 顶点属性数据 // 指定立方体顶点属性数据 顶点位置 纹理 GLfloat cubeVertices[] = { -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // A 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // B 0.5f, 0.5f, 0.5f,1.0f, 1.0f, // C 0.5f, 0.5f, 0.5f,1.0f, 1.0f, // C -0.5f, 0.5f, 0.5f,0.0f, 1.0f, // D -0.5f, -0.5f, 0.5f,0.0f, 0.0f, // A -0.5f, -0.5f, -0.5f,0.0f, 0.0f, // E -0.5f, 0.5f, -0.5f,0.0, 1.0f, // H 0.5f, 0.5f, -0.5f,1.0f, 1.0f, // G 0.5f, 0.5f, -0.5f,1.0f, 1.0f, // G 0.5f, -0.5f, -0.5f,1.0f, 0.0f, // F -0.5f, -0.5f, -0.5f,0.0f, 0.0f, // E -0.5f, 0.5f, 0.5f,0.0f, 1.0f, // D -0.5f, 0.5f, -0.5f,1.0, 1.0f, // H -0.5f, -0.5f, -0.5f,1.0f, 0.0f, // E -0.5f, -0.5f, -0.5f,1.0f, 0.0f, // E -0.5f, -0.5f, 0.5f,0.0f, 0.0f, // A -0.5f, 0.5f, 0.5f,0.0f, 1.0f, // D 0.5f, -0.5f, -0.5f,1.0f, 0.0f, // F 0.5f, 0.5f, -0.5f,1.0f, 1.0f, // G 0.5f, 0.5f, 0.5f,0.0f, 1.0f, // C 0.5f, 0.5f, 0.5f,0.0f, 1.0f, // C 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // B 0.5f, -0.5f, -0.5f,1.0f, 0.0f, // F 0.5f, 0.5f, -0.5f,1.0f, 1.0f, // G -0.5f, 0.5f, -0.5f,0.0, 1.0f, // H -0.5f, 0.5f, 0.5f,0.0f, 0.0f, // D -0.5f, 0.5f, 0.5f,0.0f, 0.0f, // D 0.5f, 0.5f, 0.5f,1.0f, 0.0f, // C 0.5f, 0.5f, -0.5f,1.0f, 1.0f, // G -0.5f, -0.5f, 0.5f,0.0f, 0.0f, // A -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,// E 0.5f, -0.5f, -0.5f,1.0f, 1.0f, // F 0.5f, -0.5f, -0.5f,1.0f, 1.0f, // F 0.5f, -0.5f, 0.5f,1.0f, 0.0f, // B -0.5f, -0.5f, 0.5f,0.0f, 0.0f, // A }; // Section2 准备缓存对象 GLuint cubeVAOId, cubeVBOId; glGenVertexArrays(1, &cubeVAOId); glGenBuffers(1, &cubeVBOId); glBindVertexArray(cubeVAOId); glBindBuffer(GL_ARRAY_BUFFER, cubeVBOId); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW); // 顶点位置数据 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (GLvoid*)0); glEnableVertexAttribArray(0); // 顶点纹理数据 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (GLvoid*)(3 * sizeof(GL_FLOAT))); glEnableVertexAttribArray(1); glBindVertexArray(0); // Section3 准备着色器程序 Shader shader("scene.vertex", "scene.frag"); glEnable(GL_MULTISAMPLE); // 开启multisample glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_CULL_FACE); // 开始游戏主循环 while (!glfwWindowShouldClose(window)) { GLfloat currentFrame = (GLfloat)glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glfwPollEvents(); // 处理例如鼠标 键盘等事件 do_movement(); // 根据用户操作情况 更新相机属性 glClearColor(0.18f, 0.04f, 0.14f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader.use(); glm::mat4 projection = glm::perspective(camera.mouse_zoom, (GLfloat)(WINDOW_WIDTH) / WINDOW_HEIGHT, 1.0f, 100.0f); // 投影矩阵 glm::mat4 view = camera.getViewMatrix(); // 视变换矩阵 glUniformMatrix4fv(glGetUniformLocation(shader.programId, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniformMatrix4fv(glGetUniformLocation(shader.programId, "view"), 1, GL_FALSE, glm::value_ptr(view)); glm::mat4 model; model = glm::mat4(); model = glm::rotate(model, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 0.0f)); glUniformMatrix4fv(glGetUniformLocation(shader.programId, "model"), 1, GL_FALSE, glm::value_ptr(model)); // 这里填写场景绘制代码 glBindVertexArray(cubeVAOId); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); glBindVertexArray(0); glUseProgram(0); glfwSwapBuffers(window); // 交换缓存 } // 释放资源 glDeleteVertexArrays(1, &cubeVAOId); glDeleteBuffers(1, &cubeVBOId); glfwTerminate(); return 0; }
// 由相机辅助类处理鼠标滚轮控制 void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { camera.handleMouseScroll(yoffset); }