int NineNodeMixedQuad::displaySelf(Renderer &theViewer, int displayMode, float fact) { // first determine the end points of the quad based on // the display factor (a measure of the distorted image) // store this information in 4 3d vectors v1 through v4 const Vector &end1Crd = nodePointers[0]->getCrds(); const Vector &end2Crd = nodePointers[4]->getCrds(); const Vector &end3Crd = nodePointers[1]->getCrds(); const Vector &end4Crd = nodePointers[5]->getCrds(); const Vector &end5Crd = nodePointers[2]->getCrds(); const Vector &end6Crd = nodePointers[6]->getCrds(); const Vector &end7Crd = nodePointers[3]->getCrds(); const Vector &end8Crd = nodePointers[7]->getCrds(); const Vector &end1Disp = nodePointers[0]->getDisp(); const Vector &end2Disp = nodePointers[4]->getDisp(); const Vector &end3Disp = nodePointers[1]->getDisp(); const Vector &end4Disp = nodePointers[5]->getDisp(); const Vector &end5Disp = nodePointers[2]->getDisp(); const Vector &end6Disp = nodePointers[6]->getDisp(); const Vector &end7Disp = nodePointers[3]->getDisp(); const Vector &end8Disp = nodePointers[7]->getDisp(); static Matrix coords(8,3) ; static Vector values(8) ; static Vector P(8) ; coords.Zero( ) ; values(0) = 1 ; values(1) = 1 ; values(2) = 1 ; values(3) = 1 ; values(4) = 1 ; values(5) = 1 ; values(6) = 1 ; values(7) = 1 ; if (displayMode < 3 && displayMode > 0) P = this->getResistingForce(); for (int i = 0; i < 2; i++) { coords(0,i) = end1Crd(i) + end1Disp(i)*fact; coords(1,i) = end2Crd(i) + end2Disp(i)*fact; coords(2,i) = end3Crd(i) + end3Disp(i)*fact; coords(3,i) = end4Crd(i) + end4Disp(i)*fact; coords(4,i) = end5Crd(i) + end5Disp(i)*fact; coords(5,i) = end6Crd(i) + end6Disp(i)*fact; coords(6,i) = end7Crd(i) + end7Disp(i)*fact; coords(7,i) = end8Crd(i) + end8Disp(i)*fact; /* if (displayMode < 3 && displayMode > 0) values(i) = P(displayMode*2+i); else values(i) = 1; */ } //opserr << coords; int error = 0; error += theViewer.drawPolygon (coords, values); return error; }
void Url::goTo() { Selection sel; if (urlStr == "") return; Simulation *sim = appCore->getSimulation(); Renderer *renderer = appCore->getRenderer(); std::string::size_type pos; sim->update(0.0); switch(type) { case Absolute:// Intentional Fall-Through case Relative: sim->setFrame(ref.getCoordinateSystem(), ref.getRefObject(), ref.getTargetObject()); sim->getActiveObserver()->setFOV(degToRad(fieldOfView)); appCore->setZoomFromFOV(); sim->setTimeScale(timeScale); sim->setPauseState(pauseState); appCore->setLightDelayActive(lightTimeDelay); if (selectedStr != "") { pos = 0; while(pos != std::string::npos) { pos = selectedStr.find(":", pos + 1); if (pos != std::string::npos) selectedStr[pos]='/'; } sel = sim->findObjectFromPath(selectedStr); sim->setSelection(sel); } else { sim->setSelection(Selection()); } if (trackedStr != "") { pos = 0; while(pos != std::string::npos) { pos = trackedStr.find(":", pos + 1); if (pos != std::string::npos) trackedStr[pos]='/'; } sel = sim->findObjectFromPath(trackedStr); sim->setTrackedObject(sel); } else { if (!sim->getTrackedObject().empty()) sim->setTrackedObject(Selection()); } // Intentional Fall-Through case Settings: renderer->setRenderFlags(renderFlags); renderer->setLabelMode(labelMode); break; } if (version >= 3) { switch (timeSource) { case UseUrlTime: sim->setTime((double) date); break; case UseSimulationTime: // Leave the current simulation time unmodified break; case UseSystemTime: sim->setTime(astro::UTCtoTDB(astro::Date::systemDate())); break; default: break; } // Position and orientation stored in frame coordinates; convert them // to universal and set the observer position. double tdb = sim->getTime(); coord = sim->getObserver().getFrame()->convertToUniversal(coord, tdb); Quatd q(orientation.w, orientation.x, orientation.y, orientation.z); q = sim->getObserver().getFrame()->convertToUniversal(q, tdb); sim->setObserverPosition(coord); sim->setObserverOrientation(Quatf((float) q.w, (float) q.x, (float) q.y, (float) q.z)); } else { switch(type) { case Absolute: sim->setTime((double) date); sim->setObserverPosition(coord); sim->setObserverOrientation(orientation); break; case Relative: sim->gotoSelectionLongLat(0, astro::kilometersToLightYears(distance), (float) (longitude * PI / 180), (float) (latitude * PI / 180), Vec3f(0, 1, 0)); break; case Settings: break; } } }
void TextureShader::Done() { Renderer* renderer = GraphicSubsystem::Instance()->GetRenderer(); renderer->GetTextureStage(0)->ResetTexture(); renderer->SetMaterial( Material() ); }
int main(int argc, char* args[]) { Renderer* renderer = new Renderer(); if(!renderer->init()) { printf( "Failed to initialize!\n" ); } else { Character* c = new Character(new Texture("res/img/dot.bmp", 200, 200)); renderer->addTexture(new Texture("res/img/waterlevel2.png", 0, 0)); renderer->render(); renderer->addTexture(c->getTexture()); bool quit = false; SDL_Event e; LoadCollisionMap lcm; list<Circle> circlesList; circlesList = lcm.load(); list<Circle> l; Circle c1(200,0,10); l.push_back(c1); CollisionDetector cd; int y = 0; while(!cd.hasCollision(circlesList, l)) { l.pop_back(); y += 1; Circle c1(200,y,10); l.push_back(c1); } y -= 1; c->setPosX(200); c->setPosY(y); renderer->render(); int mVelX = 0; int DOT_VEL = 1; while(!quit) { while(SDL_PollEvent(&e) != 0) { if(e.type == SDL_QUIT) { quit = true; } if(e.type == SDL_KEYDOWN && e.key.repeat == 0) { switch(e.key.keysym.sym) { case SDLK_LEFT: mVelX -= DOT_VEL; break; case SDLK_RIGHT: mVelX += DOT_VEL; break; } } else if(e.type == SDL_KEYUP && e.key.repeat == 0) { switch(e.key.keysym.sym) { case SDLK_LEFT: mVelX += DOT_VEL; break; case SDLK_RIGHT: mVelX -= DOT_VEL; break; } } } c->setPosX(c->getPosX() + mVelX); LoadCollisionMap lcm; list<Circle> circlesList; circlesList = lcm.load(); int mPosX = c->getPosX(); int mPosY = c->getPosY(); list<Circle> l; Circle c1(mPosX,mPosY,10); l.push_back(c1); CollisionDetector cd; int y = mPosY; while(cd.hasCollision(circlesList, l)) { l.pop_back(); y -= 1; Circle c1(mPosX,y,10); l.push_back(c1); }; while(!cd.hasCollision(circlesList, l)) { l.pop_back(); y += 1; Circle c1(mPosX,y,10); l.push_back(c1); }; c->setPosY(y); renderer->render(); } } return 0; }
/// @copydoc RendererInitialization::Initialize() bool RendererInitializationWin::Initialize() { WindowManager* pWindowManager = WindowManager::GetStaticInstance(); if( !pWindowManager ) { HELIUM_TRACE( TraceLevels::Info, ( TXT( "RendererInitializationWin::Initialize(): No window manager created. A window manager is necessary for " ) TXT( "RendererInitializationWin execution.\n" ) ) ); return false; } if( !D3D9Renderer::CreateStaticInstance() ) { return false; } Renderer* pRenderer = D3D9Renderer::GetStaticInstance(); HELIUM_ASSERT( pRenderer ); if( !pRenderer->Initialize() ) { Renderer::DestroyStaticInstance(); return false; } // Create the main application window. Config& rConfig = Config::GetStaticInstance(); StrongPtr< GraphicsConfig > spGraphicsConfig( rConfig.GetConfigObject< GraphicsConfig >( Name( TXT( "GraphicsConfig" ) ) ) ); HELIUM_ASSERT( spGraphicsConfig ); uint32_t displayWidth = spGraphicsConfig->GetWidth(); uint32_t displayHeight = spGraphicsConfig->GetHeight(); bool bFullscreen = spGraphicsConfig->GetFullscreen(); bool bVsync = spGraphicsConfig->GetVsync(); Window::Parameters windowParameters; windowParameters.pTitle = TXT( "Helium" ); windowParameters.width = displayWidth; windowParameters.height = displayHeight; windowParameters.bFullscreen = bFullscreen; m_pMainWindow = pWindowManager->Create( windowParameters ); HELIUM_ASSERT( m_pMainWindow ); if( !m_pMainWindow ) { HELIUM_TRACE( TraceLevels::Error, TXT( "Failed to create main application window.\n" ) ); return false; } m_pMainWindow->SetOnDestroyed( Delegate<Window*>( this, &RendererInitializationWin::OnMainWindowDestroyed ) ); Renderer::ContextInitParameters contextInitParams; contextInitParams.pWindow = m_pMainWindow->GetHandle(); contextInitParams.displayWidth = displayWidth; contextInitParams.displayHeight = displayHeight; contextInitParams.bFullscreen = bFullscreen; contextInitParams.bVsync = bVsync; bool bContextCreateResult = pRenderer->CreateMainContext( contextInitParams ); HELIUM_ASSERT( bContextCreateResult ); if( !bContextCreateResult ) { HELIUM_TRACE( TraceLevels::Error, TXT( "Failed to create main renderer context.\n" ) ); return false; } // Create and initialize the render resource manager. RenderResourceManager& rRenderResourceManager = RenderResourceManager::GetStaticInstance(); rRenderResourceManager.Initialize(); // Create and initialize the dynamic drawing interface. DynamicDrawer& rDynamicDrawer = DynamicDrawer::GetStaticInstance(); if( !rDynamicDrawer.Initialize() ) { HELIUM_TRACE( TraceLevels::Error, TXT( "Failed to initialize dynamic drawing support.\n" ) ); return false; } return true; }
void SceneMesh::renderMeshLocally() { Renderer *renderer = CoreServices::getInstance()->getRenderer(); if(skeleton) { for(int i=0; i < mesh->getPolygonCount(); i++) { Polygon *polygon = mesh->getPolygon(i); unsigned int vCount = polygon->getVertexCount(); for(int j=0; j < vCount; j++) { Vertex *vert = polygon->getVertex(j); Vector3 norm; Vector3 aPos = vert->restPosition; Vector3 tPos; Number mult = 1; /* Number mult = 0; for(int b =0; b < vert->getNumBoneAssignments(); b++) { BoneAssignment *bas = vert->getBoneAssignment(b); mult += bas->weight; } mult = 1.0f/mult; */ for(int b =0; b < vert->getNumBoneAssignments(); b++) { BoneAssignment *bas = vert->getBoneAssignment(b); Bone *bone = bas->bone; if(bone) { Matrix4 restMatrix = bone->getRestMatrix(); Matrix4 finalMatrix = bone->getFinalMatrix(); Vector3 vec = restMatrix * aPos; tPos += finalMatrix * vec * (bas->weight*mult); Vector3 nvec = vert->restNormal; nvec = restMatrix.rotateVector(nvec); nvec = finalMatrix.rotateVector(nvec); norm += nvec * (bas->weight*mult); } } vert->x = tPos.x; vert->y = tPos.y; vert->z = tPos.z; norm.Normalize(); vert->setNormal(norm.x, norm.y, norm.z); } } mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true; mesh->arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true; mesh->arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true; } if(mesh->useVertexColors) { renderer->pushDataArrayForMesh(mesh, RenderDataArray::COLOR_DATA_ARRAY); } renderer->pushDataArrayForMesh(mesh, RenderDataArray::VERTEX_DATA_ARRAY); renderer->pushDataArrayForMesh(mesh, RenderDataArray::NORMAL_DATA_ARRAY); renderer->pushDataArrayForMesh(mesh, RenderDataArray::TANGENT_DATA_ARRAY); renderer->pushDataArrayForMesh(mesh, RenderDataArray::TEXCOORD_DATA_ARRAY); renderer->drawArrays(mesh->getMeshType()); }
FilamentApp::CView::CView(Renderer& renderer, std::string name) : engine(*renderer.getEngine()), mName(name) { view = engine.createView(); view->setClearColor({ 0 }); view->setName(name.c_str()); }
void Screen::drawFilter() { if(!filterShaderMaterial) return; Renderer *renderer = CoreServices::getInstance()->getRenderer(); renderer->bindFrameBufferTexture(originalSceneTexture); Render(); renderer->unbindFramebuffers(); ShaderBinding* materialBinding; for(int i=0; i < filterShaderMaterial->getNumShaders(); i++) { materialBinding = filterShaderMaterial->getShaderBinding(i); for(int j=0; j < materialBinding->getNumColorTargetBindings(); j++) { RenderTargetBinding *colorBinding = materialBinding->getColorTargetBinding(j); materialBinding->clearTexture(colorBinding->name); materialBinding->addTexture(colorBinding->name, originalSceneTexture); } renderer->applyMaterial(filterShaderMaterial, localShaderOptions[i], i); if(i==filterShaderMaterial->getNumShaders()-1) { renderer->loadIdentity(); renderer->drawScreenQuad(renderer->getXRes(), renderer->getYRes()); } else { for(int j=0; j < materialBinding->getNumOutTargetBindings(); j++) { renderer->bindFrameBufferTexture(materialBinding->getOutTargetBinding(j)->texture); renderer->drawScreenQuad(materialBinding->getOutTargetBinding(j)->width, materialBinding->getOutTargetBinding(j)->height); renderer->unbindFramebuffers(); } } renderer->clearShader(); renderer->loadIdentity(); renderer->setOrthoMode(); } }
int main() { initCrashSystem(); initMemorySystem(); SDL_Init(SDL_INIT_EVERYTHING); SDL_Window *window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 640, SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE |SDL_WINDOW_SHOWN); SDL_GLContext context = createContext(window); SDL_GL_SetSwapInterval(1); bool running = true; float frametime = 0.0f; Renderer *renderer = NEW(Renderer, NEW(GLBackend)); ResourceManager *resMgr = renderer->getResourceManager(); Scene *scene = NEW(Scene, renderer); Scene *quadScene = NEW(Scene, renderer); RenderTarget *target = NEW(RenderTarget, renderer); RenderTarget *textureTarget = NEW(RenderTarget, renderer); Framebuffer *framebuffer = textureTarget->addFramebuffer(); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::RGBAU8_Norm_InternalFormat); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::Red32F_InternalFormat); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::RGBU8_Norm_InternalFormat); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::RGBAU8_Norm_InternalFormat); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::RGBU8_Norm_InternalFormat); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::RGBU8_Norm_InternalFormat); framebuffer->finish(); ResPtr<Model> model = resMgr->load("res/models/dragon.json").cast<Model>(); ResPtr<Mesh> quadMesh = resMgr->createMesh(resMgr->load("res/shaders/quad vertex.json").cast<Shader>(), Mesh::Triangles, 6); VertexBuffer *quadVB = quadMesh->addPositions(renderer, MeshComponent(2, MeshComponent::Float32))->getVertexBuffer(); quadVB->alloc(sizeof(glm::vec2)*6); glm::vec2 *quadPositions = (glm::vec2 *)quadVB->map(false, true); quadPositions[0] = glm::vec2(-1.0f, -1.0f); quadPositions[1] = glm::vec2( 1.0f, -1.0f); quadPositions[2] = glm::vec2(-1.0f, 1.0f); quadPositions[3] = glm::vec2(-1.0f, 1.0f); quadPositions[4] = glm::vec2( 1.0f, -1.0f); quadPositions[5] = glm::vec2( 1.0f, 1.0f); quadVB->unmap(); ResPtr<Material> quadMaterial = resMgr->createMaterial( resMgr->load("res/shaders/quad fragment.json").cast<Shader>()); quadMaterial->mUniforms["colorTexture"] = framebuffer->getColorTexture(0); quadMaterial->mUniforms["depthTexture"] = framebuffer->getColorTexture(1); quadMaterial->mUniforms["normalTexture"] = framebuffer->getColorTexture(2); quadMaterial->mUniforms["materialTexture"] = framebuffer->getColorTexture(3); quadMaterial->mUniforms["ambientTexture"] = framebuffer->getColorTexture(4); quadMaterial->mUniforms["specularTexture"] = framebuffer->getColorTexture(5); quadMaterial->mUniforms["lightDirection"] = glm::vec3(0.0f); ResPtr<Model> quadModel = resMgr->createModel(); quadModel->mLODs.push_back(LOD(quadMesh, quadMaterial, 0.0f)); quadModel->sortLODs(); quadScene->createEntity(quadModel); scene->mSkyboxTexture = resMgr->load("res/textures/enviroment texture.json").cast<Texture>(); Entity *entity = scene->createEntity(model); float t = 0.0f; bool fullscreen = false; glm::vec3 cameraPosition(0.0f, 0.0f, 5.0f); glm::vec2 cameraAngle(3.1415f, 0.0f); float cameraSpeed = 3.0f; float cameraRotateSpeed = 1.0f; while (running) { Uint64 start = SDL_GetPerformanceCounter(); SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: { running = false; break; } case SDL_KEYDOWN: { switch (event.key.keysym.scancode) { case SDL_SCANCODE_ESCAPE: { running = false; break; } case SDL_SCANCODE_F1: { fullscreen = not fullscreen; SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP*fullscreen); } default: {} } } } } const Uint8 *pressed = SDL_GetKeyboardState(NULL); glm::vec3 direction(std::cos(cameraAngle.y) * std::sin(cameraAngle.x), std::sin(cameraAngle.y), std::cos(cameraAngle.y) * std::cos(cameraAngle.x)); glm::vec3 right(std::sin(cameraAngle.x - 3.1415f / 2.0f), 0.0f, std::cos(cameraAngle.x - 3.1415f / 2.0f)); glm::vec3 up = glm::cross(right, direction); if (pressed[SDL_SCANCODE_LEFT]) { cameraAngle.x += cameraRotateSpeed * frametime; } else if (pressed[SDL_SCANCODE_RIGHT]) { cameraAngle.x -= cameraRotateSpeed * frametime; } else if (pressed[SDL_SCANCODE_UP]) { cameraAngle.y += cameraRotateSpeed * frametime; } else if (pressed[SDL_SCANCODE_DOWN]) { cameraAngle.y -= cameraRotateSpeed * frametime; } else if (pressed[SDL_SCANCODE_A]) { cameraPosition -= right * frametime * cameraSpeed; } else if (pressed[SDL_SCANCODE_D]) { cameraPosition += right * frametime * cameraSpeed; } else if (pressed[SDL_SCANCODE_W]) { cameraPosition += direction * frametime * cameraSpeed; } else if (pressed[SDL_SCANCODE_S]) { cameraPosition -= direction * frametime * cameraSpeed; } scene->mProjectionTransform.reset(); int windowWidth; int windowHeight; SDL_GetWindowSize(window, &windowWidth, &windowHeight); target->setWidthAndHeight(windowWidth, windowHeight); textureTarget->setWidthAndHeight(windowWidth, windowHeight); scene->mProjectionTransform.perspective(45.0f, float(windowWidth)/float(windowHeight), 0.1f, 100.0f); scene->mViewTransform.reset(); scene->mViewTransform.lookAt(cameraPosition, cameraPosition+direction, up); t += frametime; entity->mTransform.reset(); entity->mTransform.scale(glm::vec3(0.5f)); entity->mTransform.rotate(45.0f*t, glm::vec3(0.0f, 1.0f, 0.0f)); renderer->render(textureTarget, scene); quadMaterial->mUniforms["lightDirection"] = glm::mat3(scene->mViewTransform.getMatrix()) * glm::vec3(-1.0f, 1.0f, -1.0f); renderer->render(target, quadScene); SDL_GL_SwapWindow(window); resMgr->deleteUnusedResources(); Uint64 end = SDL_GetPerformanceCounter(); frametime = float(end - start) / float(SDL_GetPerformanceFrequency()); char title[256]; std::memset(title, 0, 256); std::snprintf(title, 256, "Frametime: %.4f, Framerate: %.0f", frametime, 1.0f/frametime); SDL_SetWindowTitle(window, title); } model = nullRes<Model>(); quadMesh = nullRes<Mesh>(); quadMaterial = nullRes<Material>(); quadModel = nullRes<Model>(); DELETE(RenderTarget, textureTarget); DELETE(RenderTarget, target); DELETE(Scene, quadScene); DELETE(Scene, scene); DELETE(Renderer, renderer); SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); deinitMemorySystem(); return 0; }
int ElTawil2D::displaySelf(Renderer &theViewer, int displayMode, float fact) { this->YieldSurface_BC2D::displaySelf(theViewer, displayMode, fact); Vector pOld(3), pCurr(3); Vector rgb(3); rgb(0) = 0.1; rgb(1) = 0.5; rgb(2) = 0.5; if(displayMode == this->SurfOnly) { rgb(0) = 0.7; rgb(1) = 0.7; rgb(2) = 1.0; } // double incr = ((yPosCap/capY) - (yNegCap/capY)) / 10; double incr = fabs(0.33333333*yNegCap/capY); if(fact < 1) incr = fact; double xOld = 0; double yOld = yNegCap/capY; // hModel->toDeformedCoord(xOld, yOld); double err = 1e-4; for(double yc = yNegCap/capY; yc <= yPosCap/capY + err; yc = yc+incr) { double y = yc; double yVal = y*capY; double xVal; if(y < 0) { xVal = xBal*(1 - pow( fabs(yVal/yNegCap) , ty)); } else { xVal = xBal*(1 - pow( (yVal/yPosCap) , cz)); } double x = xVal/capX; if(displayMode==100) opserr << "(undeformed) x = " << x << ", y = " << y; double x1 = x; double y1 = y; double x2 = -x; double y2 = y; double x1Old = xOld; double y1Old = yOld; double x2Old = -xOld; double y2Old = yOld; hModel->toDeformedCoord(x1, y1); hModel->toDeformedCoord(x1Old, y1Old); hModel->toDeformedCoord(x2, y2); hModel->toDeformedCoord(x2Old, y2Old); // if(displayMode==100) // opserr << " (deformed) x = " << x << ", y = " << y << endln; pCurr(0) = x1; pCurr(1) = y1; pOld(0) = x1Old; pOld(1) = y1Old; theViewer.drawLine(pOld, pCurr, rgb, rgb); pCurr(0) = x2; pCurr(1) = y2; pOld(0) = x2Old; pOld(1) = y2Old; theViewer.drawLine(pOld, pCurr, rgb, rgb); xOld = x; yOld = y; } // displayForcePoint(theViewer, displayMode, fact); return 0; }
RCBindShader::RCBindShader( const Shader* shader, Renderer& renderer ) : ShaderRenderCommand( *renderer.rtMemPool() ) , m_shader( shader ) { }
void ListBox::customRender() { Renderer* r = &Control::r_texturedRectRenderer; Renderer* hlr = &Control::r_listBoxHighlightRenderer; for(int y = 0; y < m_curRowNum; y++) { for(int x = 0; x < m_colNum; x++) { int i = y * m_colNum + x; if( i == m_items.size()) break; /* // render texture int offset_x = m_rect.x + x * m_itemWidth; int offset_y = m_rect.y + y * m_itemHeight; Rect itemRect(offset_x, offset_y, m_itemWidth, m_itemHeight); */ Rect itemRect = m_items[i].rect; if (i == m_curIndex && m_curIndex >= 0) { float gap = 2; hlr->enableShader(); hlr->setData(RENDER_PASS1, "u_x1", itemRect.x + gap); hlr->setData(RENDER_PASS1, "u_x2", itemRect.x + itemRect.w - gap); hlr->setData(RENDER_PASS1, "u_y1", Control::toGUICoord(itemRect.y + itemRect.h - gap) ); hlr->setData(RENDER_PASS1, "u_y2", Control::toGUICoord(itemRect.y + gap) ); updatePipeline(hlr, itemRect); m_quadModel.render(); hlr->disableShader(); } r->enableShader(); Rect tempRect = m_items[i].modelRect; r->setData(RENDER_PASS1, "u_texture", 0, GL_TEXTURE0, m_items[i].textureID); updatePipeline(r, tempRect); m_quadModel.render(); r->disableShader(); // render text Control::m_textEngine.render(m_items[i].text, m_items[i].textStartingX, m_items[i].textStartingY, m_itemFont.size, m_itemFont.color, m_items[i].lineBreakInfo.lineBreaks); } } }
void BatchGroup::Draw(View* view) const { Graphics* graphics = view->GetGraphics(); Renderer* renderer = view->GetRenderer(); if (instances_.Size() && !geometry_->IsEmpty()) { // Draw as individual objects if instancing not supported VertexBuffer* instanceBuffer = renderer->GetInstancingBuffer(); if (!instanceBuffer || geometryType_ != GEOM_INSTANCED) { Batch::Prepare(view, false); graphics->SetIndexBuffer(geometry_->GetIndexBuffer()); graphics->SetVertexBuffers(geometry_->GetVertexBuffers(), geometry_->GetVertexElementMasks()); for (unsigned i = 0; i < instances_.Size(); ++i) { if (graphics->NeedParameterUpdate(SP_OBJECTTRANSFORM, instances_[i].worldTransform_)) graphics->SetShaderParameter(VSP_MODEL, *instances_[i].worldTransform_); graphics->Draw(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(), geometry_->GetVertexStart(), geometry_->GetVertexCount()); } } else { Batch::Prepare(view, false); // Get the geometry vertex buffers, then add the instancing stream buffer // Hack: use a const_cast to avoid dynamic allocation of new temp vectors Vector<SharedPtr<VertexBuffer> >& vertexBuffers = const_cast<Vector<SharedPtr<VertexBuffer> >&> (geometry_->GetVertexBuffers()); PODVector<unsigned>& elementMasks = const_cast<PODVector<unsigned>&>(geometry_->GetVertexElementMasks()); vertexBuffers.Push(SharedPtr<VertexBuffer>(instanceBuffer)); elementMasks.Push(instanceBuffer->GetElementMask()); // No stream offset support, instancing buffer not pre-filled with transforms: have to fill now if (startIndex_ == M_MAX_UNSIGNED) { unsigned startIndex = 0; while (startIndex < instances_.Size()) { unsigned instances = instances_.Size() - startIndex; if (instances > instanceBuffer->GetVertexCount()) instances = instanceBuffer->GetVertexCount(); // Copy the transforms Matrix3x4* dest = (Matrix3x4*)instanceBuffer->Lock(0, instances, true); if (dest) { for (unsigned i = 0; i < instances; ++i) dest[i] = *instances_[i + startIndex].worldTransform_; instanceBuffer->Unlock(); graphics->SetIndexBuffer(geometry_->GetIndexBuffer()); graphics->SetVertexBuffers(vertexBuffers, elementMasks); graphics->DrawInstanced(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(), geometry_->GetVertexStart(), geometry_->GetVertexCount(), instances); } startIndex += instances; } } // Stream offset supported and instancing buffer has been already filled, so just draw else { graphics->SetIndexBuffer(geometry_->GetIndexBuffer()); graphics->SetVertexBuffers(vertexBuffers, elementMasks, startIndex_); graphics->DrawInstanced(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(), geometry_->GetVertexStart(), geometry_->GetVertexCount(), instances_.Size()); } // Remove the instancing buffer & element mask now vertexBuffers.Pop(); elementMasks.Pop(); } } }
void Batch::Prepare(View* view, bool setModelTransform) const { if (!vertexShader_ || !pixelShader_) return; Graphics* graphics = view->GetGraphics(); Renderer* renderer = view->GetRenderer(); Node* cameraNode = camera_ ? camera_->GetNode() : 0; Light* light = lightQueue_ ? lightQueue_->light_ : 0; Texture2D* shadowMap = lightQueue_ ? lightQueue_->shadowMap_ : 0; // Set pass / material-specific renderstates if (pass_ && material_) { bool isShadowPass = pass_->GetType() == PASS_SHADOW; BlendMode blend = pass_->GetBlendMode(); // Turn additive blending into subtract if the light is negative if (light && light->IsNegative()) { if (blend == BLEND_ADD) blend = BLEND_SUBTRACT; else if (blend == BLEND_ADDALPHA) blend = BLEND_SUBTRACTALPHA; } graphics->SetBlendMode(blend); renderer->SetCullMode(isShadowPass ? material_->GetShadowCullMode() : material_->GetCullMode(), camera_); if (!isShadowPass) { const BiasParameters& depthBias = material_->GetDepthBias(); graphics->SetDepthBias(depthBias.constantBias_, depthBias.slopeScaledBias_); } graphics->SetDepthTest(pass_->GetDepthTestMode()); graphics->SetDepthWrite(pass_->GetDepthWrite()); } // Set shaders first. The available shader parameters and their register/uniform positions depend on the currently set shaders graphics->SetShaders(vertexShader_, pixelShader_); // Set global (per-frame) shader parameters if (graphics->NeedParameterUpdate(SP_FRAME, (void*)0)) view->SetGlobalShaderParameters(); // Set camera shader parameters unsigned cameraHash = overrideView_ ? (unsigned)(size_t)camera_ + 4 : (unsigned)(size_t)camera_; if (graphics->NeedParameterUpdate(SP_CAMERA, reinterpret_cast<void*>(cameraHash))) view->SetCameraShaderParameters(camera_, true, overrideView_); // Set viewport shader parameters IntVector2 rtSize = graphics->GetRenderTargetDimensions(); IntRect viewport = graphics->GetViewport(); unsigned viewportHash = (viewport.left_) | (viewport.top_ << 8) | (viewport.right_ << 16) | (viewport.bottom_ << 24); if (graphics->NeedParameterUpdate(SP_VIEWPORT, reinterpret_cast<void*>(viewportHash))) { float rtWidth = (float)rtSize.x_; float rtHeight = (float)rtSize.y_; float widthRange = 0.5f * viewport.Width() / rtWidth; float heightRange = 0.5f * viewport.Height() / rtHeight; #ifdef URHO3D_OPENGL Vector4 bufferUVOffset(((float)viewport.left_) / rtWidth + widthRange, 1.0f - (((float)viewport.top_) / rtHeight + heightRange), widthRange, heightRange); #else Vector4 bufferUVOffset((0.5f + (float)viewport.left_) / rtWidth + widthRange, (0.5f + (float)viewport.top_) / rtHeight + heightRange, widthRange, heightRange); #endif graphics->SetShaderParameter(VSP_GBUFFEROFFSETS, bufferUVOffset); float sizeX = 1.0f / rtWidth; float sizeY = 1.0f / rtHeight; graphics->SetShaderParameter(PSP_GBUFFERINVSIZE, Vector4(sizeX, sizeY, 0.0f, 0.0f)); } // Set model or skinning transforms if (setModelTransform && graphics->NeedParameterUpdate(SP_OBJECTTRANSFORM, worldTransform_)) { if (geometryType_ == GEOM_SKINNED) { graphics->SetShaderParameter(VSP_SKINMATRICES, reinterpret_cast<const float*>(worldTransform_), 12 * numWorldTransforms_); } else graphics->SetShaderParameter(VSP_MODEL, *worldTransform_); // Set the orientation for billboards, either from the object itself or from the camera if (geometryType_ == GEOM_BILLBOARD) { if (numWorldTransforms_ > 1) graphics->SetShaderParameter(VSP_BILLBOARDROT, worldTransform_[1].RotationMatrix()); else graphics->SetShaderParameter(VSP_BILLBOARDROT, cameraNode->GetWorldRotation().RotationMatrix()); } } // Set zone-related shader parameters BlendMode blend = graphics->GetBlendMode(); // If the pass is additive, override fog color to black so that shaders do not need a separate additive path bool overrideFogColorToBlack = blend == BLEND_ADD || blend == BLEND_ADDALPHA; unsigned zoneHash = (unsigned)(size_t)zone_; if (overrideFogColorToBlack) zoneHash += 0x80000000; if (zone_ && graphics->NeedParameterUpdate(SP_ZONE, reinterpret_cast<void*>(zoneHash))) { graphics->SetShaderParameter(VSP_AMBIENTSTARTCOLOR, zone_->GetAmbientStartColor()); graphics->SetShaderParameter(VSP_AMBIENTENDCOLOR, zone_->GetAmbientEndColor().ToVector4() - zone_->GetAmbientStartColor().ToVector4()); const BoundingBox& box = zone_->GetBoundingBox(); Vector3 boxSize = box.Size(); Matrix3x4 adjust(Matrix3x4::IDENTITY); adjust.SetScale(Vector3(1.0f / boxSize.x_, 1.0f / boxSize.y_, 1.0f / boxSize.z_)); adjust.SetTranslation(Vector3(0.5f, 0.5f, 0.5f)); Matrix3x4 zoneTransform = adjust * zone_->GetInverseWorldTransform(); graphics->SetShaderParameter(VSP_ZONE, zoneTransform); graphics->SetShaderParameter(PSP_AMBIENTCOLOR, zone_->GetAmbientColor()); graphics->SetShaderParameter(PSP_FOGCOLOR, overrideFogColorToBlack ? Color::BLACK : zone_->GetFogColor()); float farClip = camera_->GetFarClip(); float fogStart = Min(zone_->GetFogStart(), farClip); float fogEnd = Min(zone_->GetFogEnd(), farClip); if (fogStart >= fogEnd * (1.0f - M_LARGE_EPSILON)) fogStart = fogEnd * (1.0f - M_LARGE_EPSILON); float fogRange = Max(fogEnd - fogStart, M_EPSILON); Vector4 fogParams(fogEnd / farClip, farClip / fogRange, 0.0f, 0.0f); Node* zoneNode = zone_->GetNode(); if (zone_->GetHeightFog() && zoneNode) { Vector3 worldFogHeightVec = zoneNode->GetWorldTransform() * Vector3(0.0f, zone_->GetFogHeight(), 0.0f); fogParams.z_ = worldFogHeightVec.y_; fogParams.w_ = zone_->GetFogHeightScale() / Max(zoneNode->GetWorldScale().y_, M_EPSILON); } graphics->SetShaderParameter(PSP_FOGPARAMS, fogParams); } // Set light-related shader parameters if (lightQueue_) { if (graphics->NeedParameterUpdate(SP_VERTEXLIGHTS, lightQueue_) && graphics->HasShaderParameter(VS, VSP_VERTEXLIGHTS)) { Vector4 vertexLights[MAX_VERTEX_LIGHTS * 3]; const PODVector<Light*>& lights = lightQueue_->vertexLights_; for (unsigned i = 0; i < lights.Size(); ++i) { Light* vertexLight = lights[i]; Node* vertexLightNode = vertexLight->GetNode(); LightType type = vertexLight->GetLightType(); // Attenuation float invRange, cutoff, invCutoff; if (type == LIGHT_DIRECTIONAL) invRange = 0.0f; else invRange = 1.0f / Max(vertexLight->GetRange(), M_EPSILON); if (type == LIGHT_SPOT) { cutoff = Cos(vertexLight->GetFov() * 0.5f); invCutoff = 1.0f / (1.0f - cutoff); } else { cutoff = -1.0f; invCutoff = 1.0f; } // Color float fade = 1.0f; float fadeEnd = vertexLight->GetDrawDistance(); float fadeStart = vertexLight->GetFadeDistance(); // Do fade calculation for light if both fade & draw distance defined if (vertexLight->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd) fade = Min(1.0f - (vertexLight->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f); Color color = vertexLight->GetEffectiveColor() * fade; vertexLights[i * 3] = Vector4(color.r_, color.g_, color.b_, invRange); // Direction vertexLights[i * 3 + 1] = Vector4(-(vertexLightNode->GetWorldDirection()), cutoff); // Position vertexLights[i * 3 + 2] = Vector4(vertexLightNode->GetWorldPosition(), invCutoff); } if (lights.Size()) graphics->SetShaderParameter(VSP_VERTEXLIGHTS, vertexLights[0].Data(), lights.Size() * 3 * 4); } } if (light && graphics->NeedParameterUpdate(SP_LIGHT, light)) { // Deferred light volume batches operate in a camera-centered space. Detect from material, zone & pass all being null bool isLightVolume = !material_ && !pass_ && !zone_; Matrix3x4 cameraEffectiveTransform = camera_->GetEffectiveWorldTransform(); Vector3 cameraEffectivePos = cameraEffectiveTransform.Translation(); Node* lightNode = light->GetNode(); Matrix3 lightWorldRotation = lightNode->GetWorldRotation().RotationMatrix(); graphics->SetShaderParameter(VSP_LIGHTDIR, lightWorldRotation * Vector3::BACK); float atten = 1.0f / Max(light->GetRange(), M_EPSILON); graphics->SetShaderParameter(VSP_LIGHTPOS, Vector4(lightNode->GetWorldPosition(), atten)); if (graphics->HasShaderParameter(VS, VSP_LIGHTMATRICES)) { switch (light->GetLightType()) { case LIGHT_DIRECTIONAL: { Matrix4 shadowMatrices[MAX_CASCADE_SPLITS]; unsigned numSplits = lightQueue_->shadowSplits_.Size(); for (unsigned i = 0; i < numSplits; ++i) CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, Vector3::ZERO); graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits); } break; case LIGHT_SPOT: { Matrix4 shadowMatrices[2]; CalculateSpotMatrix(shadowMatrices[0], light, Vector3::ZERO); bool isShadowed = shadowMap && graphics->HasTextureUnit(TU_SHADOWMAP); if (isShadowed) CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, Vector3::ZERO); graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16); } break; case LIGHT_POINT: { Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix()); // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite // the next parameter #ifdef URHO3D_OPENGL graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 16); #else graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 12); #endif } break; } } float fade = 1.0f; float fadeEnd = light->GetDrawDistance(); float fadeStart = light->GetFadeDistance(); // Do fade calculation for light if both fade & draw distance defined if (light->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd) fade = Min(1.0f - (light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f); // Negative lights will use subtract blending, so write absolute RGB values to the shader parameter graphics->SetShaderParameter(PSP_LIGHTCOLOR, Color(light->GetEffectiveColor().Abs(), light->GetEffectiveSpecularIntensity()) * fade); graphics->SetShaderParameter(PSP_LIGHTDIR, lightWorldRotation * Vector3::BACK); graphics->SetShaderParameter(PSP_LIGHTPOS, Vector4((isLightVolume ? (lightNode->GetWorldPosition() - cameraEffectivePos) : lightNode->GetWorldPosition()), atten)); if (graphics->HasShaderParameter(PS, PSP_LIGHTMATRICES)) { switch (light->GetLightType()) { case LIGHT_DIRECTIONAL: { Matrix4 shadowMatrices[MAX_CASCADE_SPLITS]; unsigned numSplits = lightQueue_->shadowSplits_.Size(); for (unsigned i = 0; i < numSplits; ++i) { CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, isLightVolume ? cameraEffectivePos : Vector3::ZERO); } graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits); } break; case LIGHT_SPOT: { Matrix4 shadowMatrices[2]; CalculateSpotMatrix(shadowMatrices[0], light, cameraEffectivePos); bool isShadowed = lightQueue_->shadowMap_ != 0; if (isShadowed) { CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, isLightVolume ? cameraEffectivePos : Vector3::ZERO); } graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16); } break; case LIGHT_POINT: { Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix()); // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite // the next parameter #ifdef URHO3D_OPENGL graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 16); #else graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 12); #endif } break; } } // Set shadow mapping shader parameters if (shadowMap) { { // Calculate point light shadow sampling offsets (unrolled cube map) unsigned faceWidth = shadowMap->GetWidth() / 2; unsigned faceHeight = shadowMap->GetHeight() / 3; float width = (float)shadowMap->GetWidth(); float height = (float)shadowMap->GetHeight(); #ifdef URHO3D_OPENGL float mulX = (float)(faceWidth - 3) / width; float mulY = (float)(faceHeight - 3) / height; float addX = 1.5f / width; float addY = 1.5f / height; #else float mulX = (float)(faceWidth - 4) / width; float mulY = (float)(faceHeight - 4) / height; float addX = 2.5f / width; float addY = 2.5f / height; #endif // If using 4 shadow samples, offset the position diagonally by half pixel if (renderer->GetShadowQuality() & SHADOWQUALITY_HIGH_16BIT) { addX -= 0.5f / width; addY -= 0.5f / height; } graphics->SetShaderParameter(PSP_SHADOWCUBEADJUST, Vector4(mulX, mulY, addX, addY)); } { // Calculate shadow camera depth parameters for point light shadows and shadow fade parameters for // directional light shadows, stored in the same uniform Camera* shadowCamera = lightQueue_->shadowSplits_[0].shadowCamera_; float nearClip = shadowCamera->GetNearClip(); float farClip = shadowCamera->GetFarClip(); float q = farClip / (farClip - nearClip); float r = -q * nearClip; const CascadeParameters& parameters = light->GetShadowCascade(); float viewFarClip = camera_->GetFarClip(); float shadowRange = parameters.GetShadowRange(); float fadeStart = parameters.fadeStart_ * shadowRange / viewFarClip; float fadeEnd = shadowRange / viewFarClip; float fadeRange = fadeEnd - fadeStart; graphics->SetShaderParameter(PSP_SHADOWDEPTHFADE, Vector4(q, r, fadeStart, 1.0f / fadeRange)); } { float intensity = light->GetShadowIntensity(); float fadeStart = light->GetShadowFadeDistance(); float fadeEnd = light->GetShadowDistance(); if (fadeStart > 0.0f && fadeEnd > 0.0f && fadeEnd > fadeStart) intensity = Lerp(intensity, 1.0f, Clamp((light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 0.0f, 1.0f)); float pcfValues = (1.0f - intensity); float samples = renderer->GetShadowQuality() >= SHADOWQUALITY_HIGH_16BIT ? 4.0f : 1.0f; graphics->SetShaderParameter(PSP_SHADOWINTENSITY, Vector4(pcfValues / samples, intensity, 0.0f, 0.0f)); } float sizeX = 1.0f / (float)shadowMap->GetWidth(); float sizeY = 1.0f / (float)shadowMap->GetHeight(); graphics->SetShaderParameter(PSP_SHADOWMAPINVSIZE, Vector4(sizeX, sizeY, 0.0f, 0.0f)); Vector4 lightSplits(M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE); if (lightQueue_->shadowSplits_.Size() > 1) lightSplits.x_ = lightQueue_->shadowSplits_[0].farSplit_ / camera_->GetFarClip(); if (lightQueue_->shadowSplits_.Size() > 2) lightSplits.y_ = lightQueue_->shadowSplits_[1].farSplit_ / camera_->GetFarClip(); if (lightQueue_->shadowSplits_.Size() > 3) lightSplits.z_ = lightQueue_->shadowSplits_[2].farSplit_ / camera_->GetFarClip(); graphics->SetShaderParameter(PSP_SHADOWSPLITS, lightSplits); } } // Set material-specific shader parameters and textures if (material_) { if (graphics->NeedParameterUpdate(SP_MATERIAL, material_)) { // Update shader parameter animations material_->UpdateShaderParameterAnimations(); const HashMap<StringHash, MaterialShaderParameter>& parameters = material_->GetShaderParameters(); for (HashMap<StringHash, MaterialShaderParameter>::ConstIterator i = parameters.Begin(); i != parameters.End(); ++i) graphics->SetShaderParameter(i->first_, i->second_.value_); } const SharedPtr<Texture>* textures = material_->GetTextures(); for (unsigned i = 0; i < MAX_MATERIAL_TEXTURE_UNITS; ++i) { TextureUnit unit = (TextureUnit)i; if (textures[i] && graphics->HasTextureUnit(unit)) graphics->SetTexture(i, textures[i]); } } // Set light-related textures if (light) { if (shadowMap && graphics->HasTextureUnit(TU_SHADOWMAP)) graphics->SetTexture(TU_SHADOWMAP, shadowMap); if (graphics->HasTextureUnit(TU_LIGHTRAMP)) { Texture* rampTexture = light->GetRampTexture(); if (!rampTexture) rampTexture = renderer->GetDefaultLightRamp(); graphics->SetTexture(TU_LIGHTRAMP, rampTexture); } if (graphics->HasTextureUnit(TU_LIGHTSHAPE)) { Texture* shapeTexture = light->GetShapeTexture(); if (!shapeTexture && light->GetLightType() == LIGHT_SPOT) shapeTexture = renderer->GetDefaultLightSpot(); graphics->SetTexture(TU_LIGHTSHAPE, shapeTexture); } } }
void LightList::QueueTiledLightCulling(Renderer& rRenderer, const Camera& rCamera) { RdrResourceCommandList* pResCommandList = rRenderer.GetActionCommandList(); Vec2 viewportSize = rRenderer.GetViewportSize(); uint tileCountX = RdrComputeOp::getThreadGroupCount((uint)viewportSize.x, TILEDLIGHTING_TILE_SIZE); uint tileCountY = RdrComputeOp::getThreadGroupCount((uint)viewportSize.y, TILEDLIGHTING_TILE_SIZE); bool tileCountChanged = false; if (m_tiledLightData.tileCountX != tileCountX || m_tiledLightData.tileCountY != tileCountY) { m_tiledLightData.tileCountX = tileCountX; m_tiledLightData.tileCountY = tileCountY; tileCountChanged = true; } ////////////////////////////////////// // Depth min max if (tileCountChanged) { if (m_tiledLightData.hDepthMinMaxTex) pResCommandList->ReleaseResource(m_tiledLightData.hDepthMinMaxTex); m_tiledLightData.hDepthMinMaxTex = pResCommandList->CreateTexture2D(tileCountX, tileCountY, RdrResourceFormat::R16G16_FLOAT, RdrResourceUsage::Default, nullptr); } // Update constants Matrix44 viewMtx; Matrix44 invProjMtx; rCamera.GetMatrices(viewMtx, invProjMtx); invProjMtx = Matrix44Inverse(invProjMtx); invProjMtx = Matrix44Transpose(invProjMtx); uint constantsSize = sizeof(Vec4) * 4; Vec4* pConstants = (Vec4*)RdrFrameMem::AllocAligned(constantsSize, 16); for (int i = 0; i < 4; ++i) { pConstants[i].x = invProjMtx.m[i][0]; pConstants[i].y = invProjMtx.m[i][1]; pConstants[i].z = invProjMtx.m[i][2]; pConstants[i].w = invProjMtx.m[i][3]; } m_tiledLightData.hDepthMinMaxConstants = pResCommandList->CreateUpdateConstantBuffer(m_tiledLightData.hDepthMinMaxConstants, pConstants, constantsSize, RdrCpuAccessFlags::Write, RdrResourceUsage::Dynamic); // Fill draw op RdrComputeOp* pDepthOp = RdrFrameMem::AllocComputeOp(); pDepthOp->shader = RdrComputeShader::TiledDepthMinMax; pDepthOp->threads[0] = tileCountX; pDepthOp->threads[1] = tileCountY; pDepthOp->threads[2] = 1; pDepthOp->ahWritableResources.assign(0, m_tiledLightData.hDepthMinMaxTex); pDepthOp->ahResources.assign(0, rRenderer.GetPrimaryDepthBuffer()); pDepthOp->ahConstantBuffers.assign(0, m_tiledLightData.hDepthMinMaxConstants); rRenderer.AddComputeOpToPass(pDepthOp, RdrPass::LightCulling); ////////////////////////////////////// // Light culling if (tileCountChanged) { if (m_tiledLightData.hLightIndices) pResCommandList->ReleaseResource(m_tiledLightData.hLightIndices); m_tiledLightData.hLightIndices = pResCommandList->CreateDataBuffer(nullptr, tileCountX * tileCountY * TILEDLIGHTING_BLOCK_SIZE, RdrResourceFormat::R16_UINT, RdrResourceUsage::Default); } // Update constants constantsSize = sizeof(TiledLightCullingParams); TiledLightCullingParams* pParams = (TiledLightCullingParams*)RdrFrameMem::AllocAligned(constantsSize, 16); Matrix44 mtxProj; rCamera.GetMatrices(pParams->mtxView, mtxProj); pParams->mtxView = Matrix44Transpose(pParams->mtxView); pParams->proj_11 = mtxProj._11; pParams->proj_22 = mtxProj._22; pParams->cameraNearDist = rCamera.GetNearDist(); pParams->cameraFarDist = rCamera.GetFarDist(); pParams->screenSize = viewportSize; pParams->fovY = rCamera.GetFieldOfViewY(); pParams->aspectRatio = rCamera.GetAspectRatio(); pParams->spotLightCount = m_spotLights.size(); pParams->pointLightCount = m_pointLights.size(); pParams->tileCountX = tileCountX; pParams->tileCountY = tileCountY; m_tiledLightData.hCullConstants = pResCommandList->CreateUpdateConstantBuffer(m_tiledLightData.hCullConstants, pParams, constantsSize, RdrCpuAccessFlags::Write, RdrResourceUsage::Dynamic); // Fill draw op RdrComputeOp* pCullOp = RdrFrameMem::AllocComputeOp(); pCullOp->threads[0] = tileCountX; pCullOp->threads[1] = tileCountY; pCullOp->threads[2] = 1; pCullOp->ahWritableResources.assign(0, m_tiledLightData.hLightIndices); pCullOp->ahResources.assign(0, m_hSpotLightListRes); pCullOp->ahResources.assign(1, m_hPointLightListRes); pCullOp->ahResources.assign(2, m_tiledLightData.hDepthMinMaxTex); pCullOp->ahConstantBuffers.assign(0, m_tiledLightData.hCullConstants); rRenderer.AddComputeOpToPass(pCullOp, RdrPass::LightCulling); }
/*---------------------------------------------------------------------*//** 描画 **//*---------------------------------------------------------------------*/ void MoveCursor::draw(const RenderCtx* rc) { if(_edchFlags != 0) { return; } // 無効化中 Renderer* rdr = rc->getRenderer(); #if 0 // テスト用のテクスチャ無し描画 rdr->bindTexture(0L); // テクスチャなし rdr->setSolidColor(127, 191, 255, 63); // 頂点カラー設定 RendererUtils::draw2dRect(rdr, _ptTouchStart->x() - 10.0f, _ptTouchStart->y() - 10.0f, 20.0f, 20.0f); Vector3F vtxarr[2] = { Vector3F((f32)_ptTouchStart->x(), (f32)_ptTouchStart->y(), 0.0f), Vector3F((f32)_ptTouchLast->x(), (f32)_ptTouchLast->y(), 0.0f) }; RendererUtils::render3dLines(rdr, vtxarr, 2, RendererUtils::LINES); rdr->setSolidColor(255, 255, 255, 255); // 頂点カラー白 #else // テクスチャを用いた描画 if((_xDiff != 0) || (_yDiff != 0)) { RectF32 vtx; RectF32 uv; // 行列を保存 ::glPushMatrix(); // テクスチャ設定 rdr->bindTexture(_texRef); // 加算 rdr->setAlphaBlendFunc(Renderer::AFUNC_ADD); // 2D 解像描画比 f32 rate2dr = Env_get2drRate(); // 状態によって色を変える rdr->setSolidColor(255, 255, 255, 255); switch(_state) { default: // 丸部分 RendererUtils::draw2dTextureRect( rdr, RectF32::setout(&vtx, (f32)(_ptTouchStart->x() - (W_CIRC / 2)), (f32)(_ptTouchStart->y() - (H_CIRC / 2)), W_CIRC, H_CIRC), Gcalc::calcTexUv(&uv, UV_CIRC_SLOW, W_TEX, H_TEX, rate2dr) ); // 棒部分 ::glTranslatef((f32)_ptTouchLast->x(), (f32)_ptTouchLast->y(), 0.0f); ::glRotatef(TFW_RAD_TO_DEG(_angle), 0.0f, 0.0f, 1.0f); RendererUtils::draw2dTextureRect( rdr, RectF32::setout(&vtx, - _length, (f32)(- H_BAR / 2), _length, H_BAR), Gcalc::calcTexUv(&uv, UV_BAR_SLOW, W_TEX, H_TEX, rate2dr) ); // 矢印部分 RendererUtils::draw2dTextureRect( rdr, RectF32::setout(&vtx, (f32)(W_ARW / 2), (f32)(- H_ARW / 2), - W_ARW, H_ARW), Gcalc::calcTexUv(&uv, UV_ARW_SLOW, W_TEX, H_TEX, rate2dr) ); break; case STATE_WALK: // 丸部分 RendererUtils::draw2dTextureRect( rdr, RectF32::setout(&vtx, (f32)(_ptTouchStart->x() - (W_CIRC / 2)), (f32)(_ptTouchStart->y() - (H_CIRC / 2)), W_CIRC, H_CIRC), Gcalc::calcTexUv(&uv, UV_CIRC_WALK, W_TEX, H_TEX, rate2dr) ); // 棒部分 ::glTranslatef((f32)_ptTouchLast->x(), (f32)_ptTouchLast->y(), 0.0f); ::glRotatef(TFW_RAD_TO_DEG(_angle), 0.0f, 0.0f, 1.0f); RendererUtils::draw2dTextureRect( rdr, RectF32::setout(&vtx, - _length, (f32)(- H_BAR / 2), _length, H_BAR), Gcalc::calcTexUv(&uv, UV_BAR_WALK, W_TEX, H_TEX, rate2dr) ); // 矢印部分 RendererUtils::draw2dTextureRect( rdr, RectF32::setout(&vtx, (f32)(W_ARW / 2), (f32)(- H_ARW / 2), - W_ARW, H_ARW), Gcalc::calcTexUv(&uv, UV_ARW_WALK, W_TEX, H_TEX, rate2dr) ); break; case STATE_RUN: // 丸部分 RendererUtils::draw2dTextureRect( rdr, RectF32::setout(&vtx, (f32)(_ptTouchStart->x() - (W_CIRC / 2)), (f32)(_ptTouchStart->y() - (H_CIRC / 2)), W_CIRC, H_CIRC), Gcalc::calcTexUv(&uv, UV_CIRC_RUN, W_TEX, H_TEX, rate2dr) ); // 棒部分 ::glTranslatef((f32)_ptTouchLast->x(), (f32)_ptTouchLast->y(), 0.0f); ::glRotatef(TFW_RAD_TO_DEG(_angle), 0.0f, 0.0f, 1.0f); RendererUtils::draw2dTextureRect( rdr, RectF32::setout(&vtx, - _length, (f32)(- H_BAR / 2), _length, H_BAR), Gcalc::calcTexUv(&uv, UV_BAR_RUN, W_TEX, H_TEX, rate2dr) ); // 矢印部分 RendererUtils::draw2dTextureRect( rdr, RectF32::setout(&vtx, (f32)(W_ARW / 2), (f32)(- H_ARW / 2), - W_ARW, H_ARW), Gcalc::calcTexUv(&uv, UV_ARW_RUN, W_TEX, H_TEX, rate2dr) ); break; } // 行列を戻す ::glPopMatrix(); } #endif }
/************************************************************************* Render text lines. *************************************************************************/ void MultiLineEditbox::cacheTextLines(const Rect& dest_area) { // text is already formatted, we just grab the lines and render them with the required alignment. Rect drawArea(dest_area); drawArea.offset(Point(-d_horzScrollbar->getScrollPosition(), -d_vertScrollbar->getScrollPosition())); Renderer* renderer = System::getSingleton().getRenderer(); const Font* fnt = getFont(); if (fnt) { // get layers to use for rendering float textZ = renderer->getZLayer(4) - renderer->getCurrentZ(); float selZ = renderer->getZLayer(3) - renderer->getCurrentZ(); // calculate final colours to use. ColourRect colours; float alpha = getEffectiveAlpha(); colour normalTextCol = d_normalTextColour; normalTextCol.setAlpha(normalTextCol.getAlpha() * alpha); colour selectTextCol = d_selectTextColour; selectTextCol.setAlpha(selectTextCol.getAlpha() * alpha); colour selectBrushCol = hasInputFocus() ? d_selectBrushColour : d_inactiveSelectBrushColour; selectBrushCol.setAlpha(selectBrushCol.getAlpha() * alpha); // Cache font info const float fLineSpacing = fnt->getLineSpacing (); // for each formatted line. for (size_t i = 0; i < d_lines.size(); ++i) { Rect lineRect(drawArea); // Check line is within the dest_area if ( lineRect.d_top < dest_area.d_bottom && lineRect.d_top + fLineSpacing > dest_area.d_top ) { const LineInfo& currLine = d_lines[i]; String lineText(d_text.substr(currLine.d_startIdx, currLine.d_length)); // if it is a simple 'no selection area' case if ((currLine.d_startIdx >= d_selectionEnd) || ((currLine.d_startIdx + currLine.d_length) <= d_selectionStart) || (d_selectionBrush == NULL)) { colours.setColours(normalTextCol); // render the complete line. d_renderCache.cacheText(lineText, fnt, LeftAligned, lineRect, textZ, colours, &dest_area); } // we have at least some selection highlighting to do else { // Start of actual rendering section. String sect; size_t sectIdx = 0, sectLen; float selStartOffset = 0.0f, selAreaWidth = 0.0f; // render any text prior to selected region of line. if (currLine.d_startIdx < d_selectionStart) { // calculate length of text section sectLen = d_selectionStart - currLine.d_startIdx; // get text for this section sect = lineText.substr(sectIdx, sectLen); sectIdx += sectLen; // get the pixel offset to the beginning of the selection area highlight. selStartOffset = fnt->getTextExtent(sect); // draw this portion of the text colours.setColours(normalTextCol); d_renderCache.cacheText(sect, fnt, LeftAligned, lineRect, textZ, colours, &dest_area); // set position ready for next portion of text lineRect.d_left += selStartOffset; } // calculate the length of the selected section sectLen = ceguimin(d_selectionEnd - currLine.d_startIdx, currLine.d_length) - sectIdx; // get the text for this section sect = lineText.substr(sectIdx, sectLen); sectIdx += sectLen; // get the extent to use as the width of the selection area highlight selAreaWidth = fnt->getTextExtent(sect); // draw the text for this section colours.setColours(selectTextCol); d_renderCache.cacheText(sect, fnt, LeftAligned, lineRect, textZ, colours, &dest_area); // render any text beyond selected region of line if (sectIdx < currLine.d_length) { // update render position to the end of the selected area. lineRect.d_left += selAreaWidth; // calculate length of this section sectLen = currLine.d_length - sectIdx; // get the text for this section sect = lineText.substr(sectIdx, sectLen); // render the text for this section. colours.setColours(normalTextCol); d_renderCache.cacheText(sect, fnt, LeftAligned, lineRect, textZ, colours, &dest_area); } // calculate area for the selection brush on this line lineRect.d_left = drawArea.d_left + selStartOffset; lineRect.d_right = lineRect.d_left + selAreaWidth; lineRect.d_bottom = lineRect.d_top + fLineSpacing; // render the selection area brush for this line colours.setColours(selectBrushCol); d_renderCache.cacheImage(*d_selectionBrush, lineRect, selZ, colours, &dest_area); } } // update master position for next line in paragraph. drawArea.d_top += fLineSpacing; } } }
bool Texture2D::SetData(SharedPtr<Image> image, bool useAlpha) { if (!image) { LOGERROR("Null image, can not set data"); return false; } unsigned memoryUse = sizeof(Texture2D); int quality = QUALITY_HIGH; Renderer* renderer = GetSubsystem<Renderer>(); if (renderer) quality = renderer->GetTextureQuality(); if (!image->IsCompressed()) { unsigned char* levelData = image->GetData(); int levelWidth = image->GetWidth(); int levelHeight = image->GetHeight(); unsigned components = image->GetComponents(); unsigned format = 0; // Discard unnecessary mip levels for (unsigned i = 0; i < mipsToSkip_[quality]; ++i) { image = image->GetNextLevel(); levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } switch (components) { case 1: format = useAlpha ? Graphics::GetAlphaFormat() : Graphics::GetLuminanceFormat(); break; case 2: format = Graphics::GetLuminanceAlphaFormat(); break; case 3: format = Graphics::GetRGBFormat(); break; case 4: format = Graphics::GetRGBAFormat(); break; } // If image was previously compressed, reset number of requested levels to avoid error if level count is too high for new size if (IsCompressed() && requestedLevels_ > 1) requestedLevels_ = 0; SetSize(levelWidth, levelHeight, format); if (!object_) return false; for (unsigned i = 0; i < levels_; ++i) { SetData(i, 0, 0, levelWidth, levelHeight, levelData); memoryUse += levelWidth * levelHeight * components; if (i < levels_ - 1) { image = image->GetNextLevel(); levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } } } else { int width = image->GetWidth(); int height = image->GetHeight(); unsigned levels = image->GetNumCompressedLevels(); unsigned format = graphics_->GetFormat(image->GetCompressedFormat()); bool needDecompress = false; if (!format) { format = Graphics::GetRGBAFormat(); needDecompress = true; } unsigned mipsToSkip = mipsToSkip_[quality]; if (mipsToSkip >= levels) mipsToSkip = levels - 1; while (mipsToSkip && (width / (1 << mipsToSkip) < 4 || height / (1 << mipsToSkip) < 4)) --mipsToSkip; width /= (1 << mipsToSkip); height /= (1 << mipsToSkip); SetNumLevels(Max((int)(levels - mipsToSkip), 1)); SetSize(width, height, format); for (unsigned i = 0; i < levels_ && i < levels - mipsToSkip; ++i) { CompressedLevel level = image->GetCompressedLevel(i + mipsToSkip); if (!needDecompress) { SetData(i, 0, 0, level.width_, level.height_, level.data_); memoryUse += level.rows_ * level.rowSize_; } else { unsigned char* rgbaData = new unsigned char[level.width_ * level.height_ * 4]; level.Decompress(rgbaData); SetData(i, 0, 0, level.width_, level.height_, rgbaData); memoryUse += level.width_ * level.height_ * 4; delete[] rgbaData; } } } SetMemoryUse(memoryUse); return true; }
bool TextureCube::SetData(CubeMapFace face, SharedPtr<Image> image, bool useAlpha) { if (!image) { LOGERROR("Null image, can not load texture"); return false; } unsigned memoryUse = 0; int quality = QUALITY_HIGH; Renderer* renderer = GetSubsystem<Renderer>(); if (renderer) quality = renderer->GetTextureQuality(); if (!image->IsCompressed()) { unsigned char* levelData = image->GetData(); int levelWidth = image->GetWidth(); int levelHeight = image->GetHeight(); unsigned components = image->GetComponents(); unsigned format = 0; if (levelWidth != levelHeight) { LOGERROR("Cube texture width not equal to height"); return false; } // Discard unnecessary mip levels for (unsigned i = 0; i < mipsToSkip_[quality]; ++i) { image = image->GetNextLevel(); levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } switch (components) { case 1: format = useAlpha ? Graphics::GetAlphaFormat() : Graphics::GetLuminanceFormat(); break; case 2: format = Graphics::GetLuminanceAlphaFormat(); break; case 3: format = Graphics::GetRGBFormat(); break; case 4: format = Graphics::GetRGBAFormat(); break; default: assert(false); // Should never reach here break; } // Create the texture when face 0 is being loaded, check that rest of the faces are same size & format if (!face) { // If image was previously compressed, reset number of requested levels to avoid error if level count is too high for new size if (IsCompressed() && requestedLevels_ > 1) requestedLevels_ = 0; SetSize(levelWidth, format); } else { if (!object_) { LOGERROR("Cube texture face 0 must be loaded first"); return false; } if (levelWidth != width_ || format != format_) { LOGERROR("Cube texture face does not match size or format of face 0"); return false; } } for (unsigned i = 0; i < levels_; ++i) { SetData(face, i, 0, 0, levelWidth, levelHeight, levelData); memoryUse += levelWidth * levelHeight * components; if (i < levels_ - 1) { image = image->GetNextLevel(); levelData = image->GetData(); levelWidth = image->GetWidth(); levelHeight = image->GetHeight(); } } } else { int width = image->GetWidth(); int height = image->GetHeight(); unsigned levels = image->GetNumCompressedLevels(); unsigned format = graphics_->GetFormat(image->GetCompressedFormat()); bool needDecompress = false; if (width != height) { LOGERROR("Cube texture width not equal to height"); return false; } if (!format) { format = Graphics::GetRGBAFormat(); needDecompress = true; } unsigned mipsToSkip = mipsToSkip_[quality]; if (mipsToSkip >= levels) mipsToSkip = levels - 1; while (mipsToSkip && (width / (1 << mipsToSkip) < 4 || height / (1 << mipsToSkip) < 4)) --mipsToSkip; width /= (1 << mipsToSkip); height /= (1 << mipsToSkip); // Create the texture when face 0 is being loaded, assume rest of the faces are same size & format if (!face) { SetNumLevels((unsigned)Max((int)(levels - mipsToSkip), 1)); SetSize(width, format); } else { if (!object_) { LOGERROR("Cube texture face 0 must be loaded first"); return false; } if (width != width_ || format != format_) { LOGERROR("Cube texture face does not match size or format of face 0"); return false; } } for (unsigned i = 0; i < levels_ && i < levels - mipsToSkip; ++i) { CompressedLevel level = image->GetCompressedLevel(i + mipsToSkip); if (!needDecompress) { SetData(face, i, 0, 0, level.width_, level.height_, level.data_); memoryUse += level.rows_ * level.rowSize_; } else { unsigned char* rgbaData = new unsigned char[level.width_ * level.height_ * 4]; level.Decompress(rgbaData); SetData(face, i, 0, 0, level.width_, level.height_, rgbaData); memoryUse += level.width_ * level.height_ * 4; delete[] rgbaData; } } } faceMemoryUse_[face] = memoryUse; unsigned totalMemoryUse = sizeof(TextureCube); for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i) totalMemoryUse += faceMemoryUse_[i]; SetMemoryUse(totalMemoryUse); return true; }
void assigment4_1_and_2() { Image img(800, 600); img.addRef(); //Set up the scene GeometryGroup scene; LWObject cow; cow.read("models/cow.obj", true); cow.addReferencesToScene(scene.primitives); scene.rebuildIndex(); BumpMirrorPhongShader sh4; sh4.diffuseCoef = float4(0.2f, 0.2f, 0, 0); sh4.ambientCoef = sh4.diffuseCoef; sh4.specularCoef = float4::rep(0.8f); sh4.specularExponent = 10000.f; sh4.reflCoef = 0.4f; sh4.addRef(); cow.materials[cow.materialMap["Floor"]].shader = &sh4; //Enable bi-linear filtering on the walls ((TexturedPhongShader*)cow.materials[cow.materialMap["Stones"]].shader.data())->diffTexture->filterMode = Texture::TFM_Bilinear; ((TexturedPhongShader*)cow.materials[cow.materialMap["Stones"]].shader.data())->amibientTexture->filterMode = Texture::TFM_Bilinear; //Set up the cameras PerspectiveCamera cam1(Point(-9.398149f, -6.266083f, 5.348377f), Point(-6.324413f, -2.961229f, 4.203216f), Vector(0, 0, 1), 30, std::make_pair(img.width(), img.height())); PerspectiveCamera cam2(Point(2.699700f, 6.437226f, 0.878297f), Point(4.337114f, 8.457443f,- 0.019007f), Vector(0, 0, 1), 30, std::make_pair(img.width(), img.height())); cam1.addRef(); cam2.addRef(); //Set up the integrator IntegratorImpl integrator; integrator.addRef(); integrator.scene = &scene; PointLightSource pls; pls.falloff = float4(0, 0, 1, 0); pls.intensity = float4::rep(0.9f); pls.position = Point(-2.473637f, 3.119330f, 9.571486f); integrator.lightSources.push_back(pls); integrator.ambientLight = float4::rep(0.1f); DefaultSampler samp; samp.addRef(); //Render Renderer r; r.integrator = &integrator; r.target = &img; r.sampler = &samp; r.camera = &cam1; r.render(); img.writePNG("result_cam1.png"); //For seeing the difference in texture filtering r.camera = &cam2; r.render(); img.writePNG("result_cam2.png"); }
void FilamentApp::run(const Config& config, SetupCallback setupCallback, CleanupCallback cleanupCallback, ImGuiCallback imguiCallback, PreRenderCallback preRender, PostRenderCallback postRender, size_t width, size_t height) { std::unique_ptr<FilamentApp::Window> window( new FilamentApp::Window(this, config, config.title, width, height)); mDepthMaterial = Material::Builder() .package((void*) DEPTH_VISUALIZER_PACKAGE, sizeof(DEPTH_VISUALIZER_PACKAGE)) .build(*mEngine); mDepthMI = mDepthMaterial->createInstance(); mDefaultMaterial = Material::Builder() .package((void*) AI_DEFAULT_MAT_PACKAGE, sizeof(AI_DEFAULT_MAT_PACKAGE)) .build(*mEngine); mTransparentMaterial = Material::Builder() .package((void*) TRANSPARENT_COLOR_PACKAGE, sizeof(TRANSPARENT_COLOR_PACKAGE)) .build(*mEngine); std::unique_ptr<Cube> cameraCube(new Cube(*mEngine, mTransparentMaterial, {1,0,0})); // we can't cull the light-frustum because it's not applied a rigid transform // and currently, filament assumes that for culling std::unique_ptr<Cube> lightmapCube(new Cube(*mEngine, mTransparentMaterial, {0,1,0}, false)); mScene = mEngine->createScene(); window->mMainView->getView()->setVisibleLayers(0x4, 0x4); window->mUiView->getView()->setClearTargets(false, false, false); window->mUiView->getView()->setRenderTarget(View::TargetBufferFlags::DEPTH_AND_STENCIL); window->mUiView->getView()->setPostProcessingEnabled(false); window->mUiView->getView()->setShadowsEnabled(false); if (config.splitView) { auto& rcm = mEngine->getRenderableManager(); rcm.setLayerMask(rcm.getInstance(cameraCube->getSolidRenderable()), 0x3, 0x2); rcm.setLayerMask(rcm.getInstance(cameraCube->getWireFrameRenderable()), 0x3, 0x2); cameraCube->mapFrustum(*mEngine, window->mMainCameraMan.getCamera()); rcm.setLayerMask(rcm.getInstance(lightmapCube->getSolidRenderable()), 0x3, 0x2); rcm.setLayerMask(rcm.getInstance(lightmapCube->getWireFrameRenderable()), 0x3, 0x2); // Create the camera mesh window->mMainCameraMan.setCameraChangedCallback( [&cameraCube, &lightmapCube, &window, engine = mEngine](Camera const* camera) { cameraCube->mapFrustum(*engine, camera); lightmapCube->mapFrustum(*engine, window->mMainView->getView()->getDirectionalLightCamera()); }); mScene->addEntity(cameraCube->getWireFrameRenderable()); mScene->addEntity(cameraCube->getSolidRenderable()); mScene->addEntity(lightmapCube->getWireFrameRenderable()); mScene->addEntity(lightmapCube->getSolidRenderable()); window->mGodView->getView()->setVisibleLayers(0x6, 0x6); window->mOrthoView->getView()->setVisibleLayers(0x6, 0x6); // only preserve the color buffer for additional views; depth and stencil can be discarded. window->mDepthView->getView()->setRenderTarget(View::TargetBufferFlags::DEPTH_AND_STENCIL); window->mGodView->getView()->setRenderTarget(View::TargetBufferFlags::DEPTH_AND_STENCIL); window->mOrthoView->getView()->setRenderTarget(View::TargetBufferFlags::DEPTH_AND_STENCIL); window->mDepthView->getView()->setShadowsEnabled(false); window->mGodView->getView()->setShadowsEnabled(false); window->mOrthoView->getView()->setShadowsEnabled(false); } loadIBL(config); if (mIBL != nullptr) { mIBL->getSkybox()->setLayerMask(0x7, 0x4); mScene->setSkybox(mIBL->getSkybox()); mScene->setIndirectLight(mIBL->getIndirectLight()); } for (auto& view : window->mViews) { if (view.get() != window->mUiView) { view->getView()->setScene(mScene); } } setupCallback(mEngine, window->mMainView->getView(), mScene); if (imguiCallback) { mImGuiHelper = std::make_unique<ImGuiHelper>(mEngine, window->mUiView->getView(), getRootPath() + "assets/fonts/Roboto-Medium.ttf"); ImGuiIO& io = ImGui::GetIO(); #ifdef WIN32 SDL_SysWMinfo wmInfo; SDL_VERSION(&wmInfo.version); SDL_GetWindowWMInfo(window->getSDLWindow(), &wmInfo); io.ImeWindowHandle = wmInfo.info.win.window; #endif io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP; io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN; io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP; io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT; io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE; io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE; io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE; io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN; io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE; io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A; io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C; io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V; io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X; io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y; io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z; io.SetClipboardTextFn = [](void*, const char* text) { SDL_SetClipboardText(text); }; io.GetClipboardTextFn = [](void*) -> const char* { return SDL_GetClipboardText(); }; io.ClipboardUserData = nullptr; } bool mousePressed[3] = { false }; while (!mClosed) { if (!UTILS_HAS_THREADING) { mEngine->execute(); } // Allow the app to animate the scene if desired. if (mAnimation) { double now = (double) SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency(); mAnimation(mEngine, window->mMainView->getView(), now); } // Loop over fresh events twice: first stash them and let ImGui process them, then allow // the app to process the stashed events. This is done because ImGui might wish to block // certain events from the app (e.g., when dragging the mouse over an obscuring window). constexpr int kMaxEvents = 16; SDL_Event events[kMaxEvents]; int nevents = 0; while (nevents < kMaxEvents && SDL_PollEvent(&events[nevents]) != 0) { if (mImGuiHelper) { ImGuiIO& io = ImGui::GetIO(); SDL_Event* event = &events[nevents]; switch (event->type) { case SDL_MOUSEWHEEL: { if (event->wheel.x > 0) io.MouseWheelH += 1; if (event->wheel.x < 0) io.MouseWheelH -= 1; if (event->wheel.y > 0) io.MouseWheel += 1; if (event->wheel.y < 0) io.MouseWheel -= 1; break; } case SDL_MOUSEBUTTONDOWN: { if (event->button.button == SDL_BUTTON_LEFT) mousePressed[0] = true; if (event->button.button == SDL_BUTTON_RIGHT) mousePressed[1] = true; if (event->button.button == SDL_BUTTON_MIDDLE) mousePressed[2] = true; break; } case SDL_TEXTINPUT: { io.AddInputCharactersUTF8(event->text.text); break; } case SDL_KEYDOWN: case SDL_KEYUP: { int key = event->key.keysym.scancode; IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown)); io.KeysDown[key] = (event->type == SDL_KEYDOWN); io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0); io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0); break; } } } nevents++; } // Now, loop over the events a second time for app-side processing. for (int i = 0; i < nevents; i++) { const SDL_Event& event = events[i]; ImGuiIO* io = mImGuiHelper ? &ImGui::GetIO() : nullptr; switch (event.type) { case SDL_QUIT: mClosed = true; break; case SDL_KEYDOWN: if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { mClosed = true; } break; case SDL_MOUSEWHEEL: if (!io || !io->WantCaptureMouse) window->mouseWheel(event.wheel.y); break; case SDL_MOUSEBUTTONDOWN: if (!io || !io->WantCaptureMouse) window->mouseDown(event.button.button, event.button.x, event.button.y); break; case SDL_MOUSEBUTTONUP: if (!io || !io->WantCaptureMouse) window->mouseUp(event.button.x, event.button.y); break; case SDL_MOUSEMOTION: if (!io || !io->WantCaptureMouse) window->mouseMoved(event.motion.x, event.motion.y); break; case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: window->resize(); break; default: break; } break; default: break; } } // Populate the UI scene, regardless of whether Filament wants to a skip frame. We should // always let ImGui generate a command list; if it skips a frame it'll destroy its widgets. if (mImGuiHelper) { // Inform ImGui of the current window size in case it was resized. int windowWidth, windowHeight; int displayWidth, displayHeight; SDL_GetWindowSize(window->mWindow, &windowWidth, &windowHeight); SDL_GL_GetDrawableSize(window->mWindow, &displayWidth, &displayHeight); mImGuiHelper->setDisplaySize(windowWidth, windowHeight, windowWidth > 0 ? ((float)displayWidth / windowWidth) : 0, displayHeight > 0 ? ((float)displayHeight / windowHeight) : 0); // Setup mouse inputs (we already got mouse wheel, keyboard keys & characters // from our event handler) ImGuiIO& io = ImGui::GetIO(); int mx, my; Uint32 buttons = SDL_GetMouseState(&mx, &my); io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); io.MouseDown[0] = mousePressed[0] || (buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; io.MouseDown[1] = mousePressed[1] || (buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; io.MouseDown[2] = mousePressed[2] || (buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; mousePressed[0] = mousePressed[1] = mousePressed[2] = false; // TODO: Update to a newer SDL and use SDL_CaptureMouse() to retrieve mouse coordinates // outside of the client area; see the imgui SDL example. if ((SDL_GetWindowFlags(window->mWindow) & SDL_WINDOW_INPUT_FOCUS) != 0) { io.MousePos = ImVec2((float)mx, (float)my); } // Populate the UI Scene. static Uint64 frequency = SDL_GetPerformanceFrequency(); Uint64 now = SDL_GetPerformanceCounter(); float timeStep = mTime > 0 ? (float)((double)(now - mTime) / frequency) : (float)(1.0f / 60.0f); mTime = now; mImGuiHelper->render(timeStep, imguiCallback); } window->mMainCameraMan.updateCameraTransform(); // TODO: we need better timing or use SDL_GL_SetSwapInterval SDL_Delay(16); Renderer* renderer = window->getRenderer(); if (preRender) { for (auto const& view : window->mViews) { if (view.get() != window->mUiView) { preRender(mEngine, view->getView(), mScene, renderer); } } } if (renderer->beginFrame(window->getSwapChain())) { for (auto const& view : window->mViews) { renderer->render(view->getView()); } renderer->endFrame(); } if (postRender) { for (auto const& view : window->mViews) { if (view.get() != window->mUiView) { postRender(mEngine, view->getView(), mScene, renderer); } } } } if (mImGuiHelper) { mImGuiHelper.reset(); } cleanupCallback(mEngine, window->mMainView->getView(), mScene); cameraCube.reset(); lightmapCube.reset(); window.reset(); mIBL.reset(); mEngine->destroy(mDepthMI); mEngine->destroy(mDepthMaterial); mEngine->destroy(mDefaultMaterial); mEngine->destroy(mTransparentMaterial); mEngine->destroy(mScene); Engine::destroy(&mEngine); mEngine = nullptr; }
void Sample::Start() { cache_ = GetSubsystem<ResourceCache>(); ui_ = GetSubsystem<UI>(); graphics_ = GetSubsystem<Graphics>(); ////////////////////////////////////////////////////////////////////////// // Get default styles XMLFile* styleFile = cache_->GetResource<XMLFile>("UI/DefaultStyle.xml"); ui_->GetRoot()->SetDefaultStyle(styleFile); // create main ui rootUI_ = ui_->GetRoot()->CreateChild<UIElement>("IDERoot"); rootUI_->SetSize(ui_->GetRoot()->GetSize()); rootUI_->SetTraversalMode(TM_DEPTH_FIRST); // This is needed for root-like element to prevent artifacts rootUI_->SetDefaultStyle(styleFile); ////////////////////////////////////////////////////////////////////////// /// Create console console_ = engine_->CreateConsole(); console_->SetDefaultStyle(styleFile); ////////////////////////////////////////////////////////////////////////// /// Create debug HUD. debugHud_ = engine_->CreateDebugHud(); debugHud_->SetDefaultStyle(styleFile); ////////////////////////////////////////////////////////////////////////// /// Subscribe key down event SubscribeToEvent(E_KEYDOWN, HANDLER(Sample, HandleKeyDown)); // edit clear color, set background color Renderer* renderer = GetSubsystem<Renderer>(); Zone* zone = renderer->GetDefaultZone(); zone->SetFogColor(Color(0.3f, 0.3f, 0.4f)); // Set background color for the scene ////////////////////////////////////////////////////////////////////////// /// Create Cursor // Cursor* cursor_ = new Cursor(context_); // cursor_->SetStyleAuto(styleFile); // ui_->SetCursor(cursor_); // if (GetPlatform() == "Android" || GetPlatform() == "iOS") // ui_->GetCursor()->SetVisible(false); /// Show Platform Cursor Input* input = GetSubsystem<Input>(); input->SetMouseVisible(true); ////////////////////////////////////////////////////////////////////////// /// create an svg image rootUI_->AddChild(CreateSVGSprite("GameData/svg/23.svg")); Sprite* drawing = CreateSVGSprite("GameData/svg/drawing.svg"); if (drawing) { // Set logo sprite hot spot drawing->SetHotSpot(0, drawing->GetHeight()); drawing->SetAlignment(HA_LEFT, VA_BOTTOM); rootUI_->AddChild(drawing); } Sprite* nano = CreateSVGSprite("GameData/svg/nano.svg"); if (nano) { // Set logo sprite hot spot nano->SetHotSpot(0, -nano->GetHeight()); nano->SetAlignment(HA_LEFT, VA_TOP); rootUI_->AddChild(nano); } }
void PhotonShootingTask::Run() { // Declare local variables for _PhotonShootingTask_ MemoryArena arena; RNG rng(31 * taskNum); vector<Photon> localDirectPhotons, localIndirectPhotons, localCausticPhotons; vector<RadiancePhoton> localRadiancePhotons; uint32_t totalPaths = 0; bool causticDone = (integrator->nCausticPhotonsWanted == 0); bool indirectDone = (integrator->nIndirectPhotonsWanted == 0); PermutedHalton halton(6, rng); vector<Spectrum> localRpReflectances, localRpTransmittances; while (true) { // Follow photon paths for a block of samples const uint32_t blockSize = 4096; for (uint32_t i = 0; i < blockSize; ++i) { float u[6]; halton.Sample(++totalPaths, u); // Choose light to shoot photon from float lightPdf; int lightNum = lightDistribution->SampleDiscrete(u[0], &lightPdf); const Light *light = scene->lights[lightNum]; // Generate _photonRay_ from light source and initialize _alpha_ RayDifferential photonRay; float pdf; LightSample ls(u[1], u[2], u[3]); Normal Nl; Spectrum Le = light->Sample_L(scene, ls, u[4], u[5], time, &photonRay, &Nl, &pdf); if (pdf == 0.f || Le.IsBlack()) continue; Spectrum alpha = (AbsDot(Nl, photonRay.d) * Le) / (pdf * lightPdf); if (!alpha.IsBlack()) { // Follow photon path through scene and record intersections PBRT_PHOTON_MAP_STARTED_RAY_PATH(&photonRay, &alpha); bool specularPath = true; Intersection photonIsect; int nIntersections = 0; while (scene->Intersect(photonRay, &photonIsect)) { ++nIntersections; // Handle photon/surface intersection alpha *= renderer->Transmittance(scene, photonRay, NULL, rng, arena); BSDF *photonBSDF = photonIsect.GetBSDF(photonRay, arena); BxDFType specularType = BxDFType(BSDF_REFLECTION | BSDF_TRANSMISSION | BSDF_SPECULAR); bool hasNonSpecular = (photonBSDF->NumComponents() > photonBSDF->NumComponents(specularType)); Vector wo = -photonRay.d; if (hasNonSpecular) { // Deposit photon at surface Photon photon(photonIsect.dg.p, alpha, wo); bool depositedPhoton = false; if (specularPath && nIntersections > 1) { if (!causticDone) { PBRT_PHOTON_MAP_DEPOSITED_CAUSTIC_PHOTON(&photonIsect.dg, &alpha, &wo); depositedPhoton = true; localCausticPhotons.push_back(photon); } } else { // Deposit either direct or indirect photon // stop depositing direct photons once indirectDone is true; don't // want to waste memory storing too many if we're going a long time // trying to get enough caustic photons desposited. if (nIntersections == 1 && !indirectDone && integrator->finalGather) { PBRT_PHOTON_MAP_DEPOSITED_DIRECT_PHOTON(&photonIsect.dg, &alpha, &wo); depositedPhoton = true; localDirectPhotons.push_back(photon); } else if (nIntersections > 1 && !indirectDone) { PBRT_PHOTON_MAP_DEPOSITED_INDIRECT_PHOTON(&photonIsect.dg, &alpha, &wo); depositedPhoton = true; localIndirectPhotons.push_back(photon); } } // Possibly create radiance photon at photon intersection point if (depositedPhoton && integrator->finalGather && rng.RandomFloat() < .125f) { Normal n = photonIsect.dg.nn; n = Faceforward(n, -photonRay.d); localRadiancePhotons.push_back(RadiancePhoton(photonIsect.dg.p, n)); Spectrum rho_r = photonBSDF->rho(rng, BSDF_ALL_REFLECTION); localRpReflectances.push_back(rho_r); Spectrum rho_t = photonBSDF->rho(rng, BSDF_ALL_TRANSMISSION); localRpTransmittances.push_back(rho_t); } } if (nIntersections >= integrator->maxPhotonDepth) break; // Sample new photon ray direction Vector wi; float pdf; BxDFType flags; Spectrum fr = photonBSDF->Sample_f(wo, &wi, BSDFSample(rng), &pdf, BSDF_ALL, &flags); if (fr.IsBlack() || pdf == 0.f) break; Spectrum anew = alpha * fr * AbsDot(wi, photonBSDF->dgShading.nn) / pdf; // Possibly terminate photon path with Russian roulette float continueProb = min(1.f, anew.y() / alpha.y()); if (rng.RandomFloat() > continueProb) break; alpha = anew / continueProb; specularPath &= ((flags & BSDF_SPECULAR) != 0); if (indirectDone && !specularPath) break; photonRay = RayDifferential(photonIsect.dg.p, wi, photonRay, photonIsect.rayEpsilon); } PBRT_PHOTON_MAP_FINISHED_RAY_PATH(&photonRay, &alpha); } arena.FreeAll(); } // Merge local photon data with data in _PhotonIntegrator_ { MutexLock lock(mutex); // Give up if we're not storing enough photons if (abortTasks) return; if (nshot > 500000 && (unsuccessful(integrator->nCausticPhotonsWanted, causticPhotons.size(), blockSize) || unsuccessful(integrator->nIndirectPhotonsWanted, indirectPhotons.size(), blockSize))) { Error("Unable to store enough photons. Giving up.\n"); causticPhotons.erase(causticPhotons.begin(), causticPhotons.end()); indirectPhotons.erase(indirectPhotons.begin(), indirectPhotons.end()); radiancePhotons.erase(radiancePhotons.begin(), radiancePhotons.end()); abortTasks = true; return; } progress.Update(localIndirectPhotons.size() + localCausticPhotons.size()); nshot += blockSize; // Merge indirect photons into shared array if (!indirectDone) { integrator->nIndirectPaths += blockSize; for (uint32_t i = 0; i < localIndirectPhotons.size(); ++i) indirectPhotons.push_back(localIndirectPhotons[i]); localIndirectPhotons.erase(localIndirectPhotons.begin(), localIndirectPhotons.end()); if (indirectPhotons.size() >= integrator->nIndirectPhotonsWanted) indirectDone = true; nDirectPaths += blockSize; for (uint32_t i = 0; i < localDirectPhotons.size(); ++i) directPhotons.push_back(localDirectPhotons[i]); localDirectPhotons.erase(localDirectPhotons.begin(), localDirectPhotons.end()); } // Merge direct, caustic, and radiance photons into shared array if (!causticDone) { integrator->nCausticPaths += blockSize; for (uint32_t i = 0; i < localCausticPhotons.size(); ++i) causticPhotons.push_back(localCausticPhotons[i]); localCausticPhotons.erase(localCausticPhotons.begin(), localCausticPhotons.end()); if (causticPhotons.size() >= integrator->nCausticPhotonsWanted) causticDone = true; } for (uint32_t i = 0; i < localRadiancePhotons.size(); ++i) radiancePhotons.push_back(localRadiancePhotons[i]); localRadiancePhotons.erase(localRadiancePhotons.begin(), localRadiancePhotons.end()); for (uint32_t i = 0; i < localRpReflectances.size(); ++i) rpReflectances.push_back(localRpReflectances[i]); localRpReflectances.erase(localRpReflectances.begin(), localRpReflectances.end()); for (uint32_t i = 0; i < localRpTransmittances.size(); ++i) rpTransmittances.push_back(localRpTransmittances[i]); localRpTransmittances.erase(localRpTransmittances.begin(), localRpTransmittances.end()); } // Exit task if enough photons have been found if (indirectDone && causticDone) break; } }
void Sample::HandleKeyDown(StringHash eventType, VariantMap& eventData) { using namespace KeyDown; int key = eventData[P_KEY].GetInt(); // Close console (if open) or exit when ESC is pressed if (key == KEY_ESC) { Console* console = GetSubsystem<Console>(); if (console->IsVisible()) console->SetVisible(false); else GetSubsystem<Engine>()->Exit(); } // Toggle console with F1 else if (key == KEY_F1) GetSubsystem<Console>()->Toggle(); // Toggle debug HUD with F2 else if (key == KEY_F2) GetSubsystem<DebugHud>()->ToggleAll(); // Take screenshot else if (key == '9') { Graphics* graphics = GetSubsystem<Graphics>(); Image screenshot(context_); graphics->TakeScreenShot(screenshot); // Here we save in the Data folder with date and time appended screenshot.SavePNG(GetSubsystem<FileSystem>()->GetProgramDir() + "Data/Screenshot_" + Time::GetTimeStamp().Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_') + ".png"); } // Common rendering quality controls, only when UI has no focused element else if (!GetSubsystem<UI>()->GetFocusElement()) { Renderer* renderer = GetSubsystem<Renderer>(); // Texture quality if (key == '1') { int quality = renderer->GetTextureQuality(); ++quality; if (quality > QUALITY_HIGH) quality = QUALITY_LOW; renderer->SetTextureQuality(quality); } // Material quality else if (key == '2') { int quality = renderer->GetMaterialQuality(); ++quality; if (quality > QUALITY_HIGH) quality = QUALITY_LOW; renderer->SetMaterialQuality(quality); } // Specular lighting else if (key == '3') renderer->SetSpecularLighting(!renderer->GetSpecularLighting()); // Shadow rendering else if (key == '4') renderer->SetDrawShadows(!renderer->GetDrawShadows()); // Shadow map resolution else if (key == '5') { int shadowMapSize = renderer->GetShadowMapSize(); shadowMapSize *= 2; if (shadowMapSize > 2048) shadowMapSize = 512; renderer->SetShadowMapSize(shadowMapSize); } // Shadow depth and filtering quality else if (key == '6') { int quality = renderer->GetShadowQuality(); ++quality; if (quality > SHADOWQUALITY_HIGH_24BIT) quality = SHADOWQUALITY_LOW_16BIT; renderer->SetShadowQuality(quality); } // Occlusion culling else if (key == '7') { bool occlusion = renderer->GetMaxOccluderTriangles() > 0; occlusion = !occlusion; renderer->SetMaxOccluderTriangles(occlusion ? 5000 : 0); } // Instancing else if (key == '8') renderer->SetDynamicInstancing(!renderer->GetDynamicInstancing()); } }
Url::Url(CelestiaCore* core, UrlType type) { appCore = core; version = 2; timeSource = UseUrlTime; Simulation *sim = appCore->getSimulation(); Renderer *renderer = appCore->getRenderer(); this->type = type; modeStr = getCoordSysName(sim->getFrame()->getCoordinateSystem()); if (type == Settings) modeStr = "Settings"; ref = *sim->getFrame(); urlStr += "cel://" + modeStr; if (type != Settings && sim->getFrame()->getCoordinateSystem() != ObserverFrame::Universal) { body1 = getSelectionName(sim->getFrame()->getRefObject()); urlStr += "/" + body1; if (sim->getFrame()->getCoordinateSystem() == ObserverFrame::PhaseLock) { body2 = getSelectionName(sim->getFrame()->getTargetObject()); urlStr += "/" + body2; } } double simTime = sim->getTime(); char date_str[50]; date = astro::Date(simTime); char buff[255]; switch (type) { case Absolute: snprintf(date_str, sizeof(date_str), "%04d-%02d-%02dT%02d:%02d:%08.5f", date.year, date.month, date.day, date.hour, date.minute, date.seconds); coord = sim->getObserver().getPosition(); urlStr += std::string("/") + date_str + "?x=" + coord.x.toString(); urlStr += "&y=" + coord.y.toString(); urlStr += "&z=" + coord.z.toString(); orientation = sim->getObserver().getOrientationf(); sprintf(buff, "&ow=%f&ox=%f&oy=%f&oz=%f", orientation.w, orientation.x, orientation.y, orientation.z); urlStr += buff; break; case Relative: sim->getSelectionLongLat(distance, longitude, latitude); sprintf(buff, "dist=%f&long=%f&lat=%f", distance, longitude, latitude); urlStr += std::string("/?") + buff; break; case Settings: urlStr += std::string("/?"); break; } switch (type) { case Absolute: // Intentional Fall-Through case Relative: tracked = sim->getTrackedObject(); trackedStr = getSelectionName(tracked); if (trackedStr != "") urlStr += "&track=" + trackedStr; selected = sim->getSelection(); selectedStr = getSelectionName(selected); if (selectedStr != "") urlStr += "&select=" + selectedStr; fieldOfView = radToDeg(sim->getActiveObserver()->getFOV()); timeScale = (float) sim->getTimeScale(); pauseState = sim->getPauseState(); lightTimeDelay = appCore->getLightDelayActive(); sprintf(buff, "&fov=%f&ts=%f<d=%c&p=%c&", fieldOfView, timeScale, lightTimeDelay?'1':'0', pauseState?'1':'0'); urlStr += buff; case Settings: // Intentional Fall-Through renderFlags = renderer->getRenderFlags(); labelMode = renderer->getLabelMode(); sprintf(buff, "rf=%d&lm=%d", renderFlags, labelMode); urlStr += buff; break; } // Append the Celestia URL version { char buf[32]; sprintf(buf, "&ver=%u", version); urlStr += buf; } evalName(); }
void Enemy::Draw(Renderer &r) { SDL_RenderCopyEx(r.getRender(), m_texture, NULL, m_render_rect, directionAngle, NULL,SDL_FLIP_NONE); }
void EnvMapShader::Apply( UInt32 /*iPass*/ ) { Renderer* renderer = GraphicSubsystem::Instance()->GetRenderer(); renderer->GetTextureStage(0)->SetTextureCoordGenMode( TextureStage::Gen_ReflectionMap ); renderer->SetRenderState( Renderer::TextureGenS, true ); renderer->SetRenderState( Renderer::TextureGenT, true ); renderer->SetRenderState( Renderer::TextureGenR, true ); Matrix4f pView; Vector3f pos(0,0,0); Vector3f dir = renderer->GetViewDir(); Vector3f up = renderer->GetViewUp(); pView.LookAt( pos, pos+dir, up ); renderer->SetMatrixMode( Renderer::TextureMatrix ); renderer->PushMatrix(); renderer->LoadIdentity(); renderer->MultMatrix( pView ); renderer->SetMatrixMode( Renderer::ModelViewMatrix ); renderer->GetTextureStage(0)->SetTexture( *mEnvironment ); }
void LightList::QueueDraw(Renderer& rRenderer, const Sky& rSky, const Camera& rCamera, const float sceneDepthMin, const float sceneDepthMax, RdrLightingMethod lightingMethod, RdrLightResources* pOutResources) { Camera lightCamera; int curShadowMapIndex = 0; int curShadowCubeMapIndex = 0; int shadowMapsThisFrame = 0; // Update shadow casting lights and the global light constants // todo: Choose shadow lights based on location and dynamic object movement GlobalLightData* pGlobalLights = (GlobalLightData*)RdrFrameMem::AllocAligned(sizeof(GlobalLightData), 16); // Temporarily add sky light to the light list. m_directionalLights.push(rSky.GetSunLight()); for (uint i = 0, count = m_directionalLights.size(); i < count; ++i) { DirectionalLight& rDirLight = m_directionalLights[i]; int remainingShadowMaps = MAX_SHADOW_MAPS - curShadowMapIndex - 1; const int kNumCascades = 4; if (remainingShadowMaps >= kNumCascades) { // Directional lights always change because they're based on camera position/rotation rDirLight.shadowMapIndex = curShadowMapIndex; Rect viewport(0.f, 0.f, (float)s_shadowMapSize, (float)s_shadowMapSize); float zMin = sceneDepthMin; float zMax = sceneDepthMax; float zDiff = (zMax - zMin); float nearDepth = zMin; float lamda = rSky.GetPssmLambda(); for (int iPartition = 0; iPartition < kNumCascades; ++iPartition) { float zUni = zMin + (zDiff / kNumCascades) * (iPartition + 1); float zLog = zMin * powf(zMax / zMin, (iPartition + 1) / (float)kNumCascades); float farDepth = lamda * zLog + (1.f - lamda) * zUni; Vec3 center = rCamera.GetPosition() + rCamera.GetDirection() * ((farDepth + nearDepth) * 0.5f); Matrix44 lightViewMtx = getLightViewMatrix(center, rDirLight.direction); Quad nearQuad = rCamera.GetFrustumQuad(nearDepth); QuadTransform(nearQuad, lightViewMtx); Quad farQuad = rCamera.GetFrustumQuad(farDepth); QuadTransform(farQuad, lightViewMtx); Vec3 boundsMin(FLT_MAX, FLT_MAX, FLT_MAX); Vec3 boundsMax(-FLT_MAX, -FLT_MAX, -FLT_MAX); accumQuadMinMax(nearQuad, boundsMin, boundsMax); accumQuadMinMax(farQuad, boundsMin, boundsMax); float height = (boundsMax.y - boundsMin.y); float width = (boundsMax.x - boundsMin.x); lightCamera.SetAsOrtho(center, rDirLight.direction, std::max(width, height), -500.f, 500.f); rRenderer.QueueShadowMapPass(lightCamera, m_shadowMapDepthViews[curShadowMapIndex], viewport); Matrix44 mtxView; Matrix44 mtxProj; lightCamera.GetMatrices(mtxView, mtxProj); pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj = Matrix44Multiply(mtxView, mtxProj); pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj = Matrix44Transpose(pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj); pGlobalLights->shadowData[curShadowMapIndex].partitionEndZ = (iPartition == kNumCascades - 1) ? FLT_MAX : farDepth; ++shadowMapsThisFrame; ++curShadowMapIndex; nearDepth = farDepth; } } else { rDirLight.shadowMapIndex = -1; } } for (uint i = 0, count = m_spotLights.size(); i < count; ++i) { SpotLight& rSpotLight = m_spotLights[i]; int remainingShadowMaps = MAX_SHADOW_MAPS - curShadowMapIndex - 1; if (remainingShadowMaps) { Matrix44 mtxView; Matrix44 mtxProj; float angle = rSpotLight.outerConeAngle + Maths::DegToRad(5.f); lightCamera.SetAsPerspective(rSpotLight.position, rSpotLight.direction, angle * 2.f, 1.f, 0.1f, 1000.f); lightCamera.GetMatrices(mtxView, mtxProj); pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj = Matrix44Multiply(mtxView, mtxProj); pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj = Matrix44Transpose(pGlobalLights->shadowData[curShadowMapIndex].mtxViewProj); Rect viewport(0.f, 0.f, (float)s_shadowMapSize, (float)s_shadowMapSize); rRenderer.QueueShadowMapPass(lightCamera, m_shadowMapDepthViews[curShadowMapIndex], viewport); rSpotLight.shadowMapIndex = curShadowMapIndex; ++shadowMapsThisFrame; ++curShadowMapIndex; } else { rSpotLight.shadowMapIndex = -1; } } for (uint i = 0, count = m_pointLights.size(); i < count; ++i) { PointLight& rPointLight = m_pointLights[i]; int remainingShadowCubeMaps = MAX_SHADOW_CUBEMAPS - curShadowCubeMapIndex - 1; if (remainingShadowCubeMaps) { rPointLight.shadowMapIndex = curShadowCubeMapIndex + MAX_SHADOW_MAPS; Rect viewport(0.f, 0.f, (float)s_shadowCubeMapSize, (float)s_shadowCubeMapSize); #if USE_SINGLEPASS_SHADOW_CUBEMAP rRenderer.QueueShadowCubeMapPass(rPointLight, m_shadowCubeMapDepthViews[curShadowCubeMapIndex], viewport); #else for (uint face = 0; face < 6; ++face) { lightCamera.SetAsCubemapFace(light.position, (CubemapFace)face, 0.1f, light.radius * 2.f); rRenderer.QueueShadowMapPass(lightCamera, m_shadowCubeMapDepthViews[curShadowCubeMapIndex * 6 + face], viewport); } #endif ++shadowMapsThisFrame; ++curShadowCubeMapIndex; } else { rPointLight.shadowMapIndex = -1; } } ////////////////////////////////////////////////////////////////////////// // Apply resource updates RdrResourceCommandList* pResCommandList = rRenderer.GetActionCommandList(); // Update spot lights SpotLight* pSpotLights = (SpotLight*)RdrFrameMem::Alloc(sizeof(SpotLight) * m_spotLights.size()); memcpy(pSpotLights, m_spotLights.getData(), sizeof(SpotLight) * m_spotLights.size()); if (!m_hSpotLightListRes) m_hSpotLightListRes = pResCommandList->CreateStructuredBuffer(pSpotLights, m_spotLights.capacity(), sizeof(SpotLight), RdrResourceUsage::Dynamic); else pResCommandList->UpdateBuffer(m_hSpotLightListRes, pSpotLights, sizeof(SpotLight) * m_spotLights.size()); // Update point lights PointLight* pPointLights = (PointLight*)RdrFrameMem::Alloc(sizeof(PointLight) * m_pointLights.size()); memcpy(pPointLights, m_pointLights.getData(), sizeof(PointLight) * m_pointLights.size()); if (!m_hPointLightListRes) m_hPointLightListRes = pResCommandList->CreateStructuredBuffer(pPointLights, m_pointLights.capacity(), sizeof(PointLight), RdrResourceUsage::Dynamic); else pResCommandList->UpdateBuffer(m_hPointLightListRes, pPointLights, sizeof(PointLight) * m_pointLights.size()); // Update environment lights EnvironmentLight* pEnvironmentLights = (EnvironmentLight*)RdrFrameMem::Alloc(sizeof(EnvironmentLight) * m_environmentLights.size()); memcpy(pEnvironmentLights, m_environmentLights.getData(), sizeof(EnvironmentLight) * m_environmentLights.size()); if (!m_hEnvironmentLightListRes) m_hEnvironmentLightListRes = pResCommandList->CreateStructuredBuffer(pEnvironmentLights, m_environmentLights.capacity(), sizeof(EnvironmentLight), RdrResourceUsage::Dynamic); else pResCommandList->UpdateBuffer(m_hEnvironmentLightListRes, pEnvironmentLights, sizeof(EnvironmentLight) * m_environmentLights.size()); // Light culling if (lightingMethod == RdrLightingMethod::Clustered) { QueueClusteredLightCulling(rRenderer, rCamera); } else { QueueTiledLightCulling(rRenderer, rCamera); } // Update global lights constant buffer last so the light culling data is up to date. pGlobalLights->numDirectionalLights = m_directionalLights.size(); pGlobalLights->globalEnvironmentLight = m_globalEnvironmentLight; pGlobalLights->clusterTileSize = m_clusteredLightData.clusterTileSize; memcpy(pGlobalLights->directionalLights, m_directionalLights.getData(), sizeof(DirectionalLight) * pGlobalLights->numDirectionalLights); m_hGlobalLightsCb = pResCommandList->CreateUpdateConstantBuffer(m_hGlobalLightsCb, pGlobalLights, sizeof(GlobalLightData), RdrCpuAccessFlags::Write, RdrResourceUsage::Dynamic); // Remove sky light. m_directionalLights.pop(); // Fill out resource params pOutResources->hGlobalLightsCb = m_hGlobalLightsCb; pOutResources->hSpotLightListRes = m_hSpotLightListRes; pOutResources->hPointLightListRes = m_hPointLightListRes; pOutResources->hEnvironmentLightListRes = m_hEnvironmentLightListRes; pOutResources->hShadowCubeMapTexArray = m_hShadowCubeMapTexArray; pOutResources->hShadowMapTexArray = m_hShadowMapTexArray; pOutResources->hEnvironmentMapTexArray = m_hEnvironmentMapTexArray; pOutResources->hLightIndicesRes = (lightingMethod == RdrLightingMethod::Clustered) ? m_clusteredLightData.hLightIndices : m_tiledLightData.hLightIndices; }
void UiRenderer::renderScreen(Renderer &renderer) { int vpWidth, vpHeight; renderer.getViewport()->getSize(&vpWidth, &vpHeight); Camera camera; camera.setOrthographic(); camera.setBounds(0, vpWidth, 0, vpHeight); Matrix4f widget; widget.translate(Vector3f(vpWidth/2, vpHeight/2, -5)); widget.scale(Vector3f(vpWidth, vpHeight, 1)); const Mesh &mesh = MeshLoader::getMesh("GUIElement.obj"); Shader &sh = ShaderLoader::getShader("color.frag"); Vector4f screenBackgroundColor = renderer.getScene()->screen->backgroundColor; glUseProgram(sh.handle); glUniform4f(sh.uni("color"), screenBackgroundColor.r, screenBackgroundColor.g, screenBackgroundColor.b, screenBackgroundColor.a); renderer.renderMesh(camera, sh, widget, mesh, nullptr); renderer.setFontColor(renderer.getScene()->screen->textColor); renderer.setFontSize(4); renderer.renderText(camera, renderer.getScene()->screen->title, Vector3f((vpWidth/2)-(renderer.getTextWidth(renderer.getScene()->screen->title)/2), vpHeight/2, -1)); renderer.setFontSize(0.5); renderer.renderText(camera, renderer.getScene()->screen->text, Vector3f((vpWidth/2)-(renderer.getTextWidth(renderer.getScene()->screen->text)/2), (vpHeight/2)-100, -1)); }
/// @copydoc GameObject::BeginPrecacheResourceData() bool Material::BeginPrecacheResourceData() { #if HELIUM_TOOLS // Convert shader options to variant indices if we just loaded a set of options. if( m_bLoadedOptions ) { MemoryZero( m_persistentResourceData.m_shaderVariantIndices, sizeof( m_persistentResourceData.m_shaderVariantIndices ) ); Shader* pShader = m_spShader; if( pShader ) { const Shader::Options& rUserOptions = pShader->GetUserOptions(); for( size_t shaderTypeIndex = 0; shaderTypeIndex < HELIUM_ARRAY_COUNT( m_persistentResourceData.m_shaderVariantIndices ); ++shaderTypeIndex ) { m_persistentResourceData.m_shaderVariantIndices[ shaderTypeIndex ] = static_cast< uint32_t >( rUserOptions.GetOptionSetIndex( static_cast< RShader::EType >( shaderTypeIndex ), m_userOptions.GetData(), m_userOptions.GetSize() ) ); } } m_userOptions.Clear(); m_bLoadedOptions = false; } #endif // Preload shader variant resources. Shader* pShader = m_spShader; if( !pShader ) { for( size_t shaderTypeIndex = 0; shaderTypeIndex < HELIUM_ARRAY_COUNT( m_shaderVariants ); ++shaderTypeIndex ) { HELIUM_ASSERT( IsInvalid( m_shaderVariantLoadIds[ shaderTypeIndex ] ) ); m_shaderVariants[ shaderTypeIndex ].Release(); } } else { for( size_t shaderTypeIndex = 0; shaderTypeIndex < HELIUM_ARRAY_COUNT( m_shaderVariants ); ++shaderTypeIndex ) { HELIUM_ASSERT( IsInvalid( m_shaderVariantLoadIds[ shaderTypeIndex ] ) ); m_shaderVariantLoadIds[ shaderTypeIndex ] = pShader->BeginLoadVariant( static_cast< RShader::EType >( shaderTypeIndex ), m_persistentResourceData.m_shaderVariantIndices[ shaderTypeIndex ] ); } } // Preload the constant buffers for shader parameters. Renderer* pRenderer = Renderer::GetStaticInstance(); if( pRenderer ) { for( size_t shaderTypeIndex = 0; shaderTypeIndex < HELIUM_ARRAY_COUNT( m_constantBuffers ); ++shaderTypeIndex ) { HELIUM_ASSERT( !m_constantBuffers[ shaderTypeIndex ] ); HELIUM_ASSERT( IsInvalid( m_constantBufferLoadIds[ shaderTypeIndex ] ) ); size_t bufferSize = GetSubDataSize( static_cast< uint32_t >( shaderTypeIndex ) ); if( bufferSize == 0 ) { continue; } RConstantBufferPtr spBuffer = pRenderer->CreateConstantBuffer( bufferSize, RENDERER_BUFFER_USAGE_STATIC ); if( !spBuffer ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Material::BeginPrecacheResourceData(): Failed to allocate constant buffer of %" ) TPRIuSZ TXT( " bytes for parameter usage for material \"%s\".\n" ) ), bufferSize, *GetPath().ToString() ); continue; } void* pBufferData = spBuffer->Map(); if( !pBufferData ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Material::BeginPrecacheResourceData(): Failed to map constant buffer data for " ) TXT( "material \"%s\".\n" ) ), *GetPath().ToString() ); continue; } size_t loadId = BeginLoadSubData( pBufferData, static_cast< uint32_t >( shaderTypeIndex ) ); if( IsInvalid( loadId ) ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Material::BeginPrecacheResourceData(): Failed to begin loading resource sub-data %" ) TPRIuSZ TXT( " for material \"%s\".\n" ) ), shaderTypeIndex, *GetPath().ToString() ); spBuffer->Unmap(); continue; } m_constantBuffers[ shaderTypeIndex ] = spBuffer; m_constantBufferLoadIds[ shaderTypeIndex ] = loadId; } } return true; }