void DrawBatch::setupVBIB( Mesh *copy_from,VFTYPE vft ) { vb = new VertexBuffer(); ib = new IndexBuffer(); if(copy_from) { vb->setFormat(copy_from->vb->fmt); vb->reserve(copy_from->vb->array_len); vb->copyFromBuffer(copy_from->vb->buf,copy_from->vb->array_len); ib->reserve(copy_from->ib->array_len); ib->copyFromBuffer(copy_from->ib->buf,copy_from->ib->array_len); prim_type = copy_from->prim_type; index_used = copy_from->ib->render_len; vert_used = copy_from->vb->array_len; } else { VertexFormat *vf = getVertexFormat(vft); vb->setFormat(vf); vb->reserve(MAXVERTEX); ib->reserve(MAXINDEX); } }
void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges) { PerformanceTimer perfTimer("ViveControllerManager::updateRendering"); if (_modelLoaded) { //auto controllerPayload = new render::Payload<ViveControllerManager>(this); //auto controllerPayloadPointer = ViveControllerManager::PayloadPointer(controllerPayload); //if (_leftHandRenderID == 0) { // _leftHandRenderID = scene->allocateID(); // pendingChanges.resetItem(_leftHandRenderID, controllerPayloadPointer); //} //pendingChanges.updateItem(_leftHandRenderID, ); UserInputMapper::PoseValue leftHand = _poseStateMap[makeInput(JointChannel::LEFT_HAND).getChannel()]; UserInputMapper::PoseValue rightHand = _poseStateMap[makeInput(JointChannel::RIGHT_HAND).getChannel()]; gpu::Batch batch; auto geometryCache = DependencyManager::get<GeometryCache>(); geometryCache->useSimpleDrawPipeline(batch); DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, true); auto mesh = _modelGeometry.getMesh(); batch.setInputFormat(mesh->getVertexFormat()); //batch._glBindTexture(GL_TEXTURE_2D, _uexture); if (leftHand.isValid()) { renderHand(leftHand, batch, LEFT_HAND); } if (rightHand.isValid()) { renderHand(rightHand, batch, RIGHT_HAND); } args->_context->syncCache(); args->_context->render(batch); } }
void DeferredLightingEffect::render(const render::RenderContextPointer& renderContext) { auto args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { // Allocate the parameters buffer used by all the deferred shaders if (!_deferredTransformBuffer[0]._buffer) { DeferredTransform parameters; _deferredTransformBuffer[0] = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(DeferredTransform), (const gpu::Byte*) ¶meters)); _deferredTransformBuffer[1] = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(DeferredTransform), (const gpu::Byte*) ¶meters)); } // Framebuffer copy operations cannot function as multipass stereo operations. batch.enableStereo(false); // perform deferred lighting, rendering to free fbo auto framebufferCache = DependencyManager::get<FramebufferCache>(); auto textureCache = DependencyManager::get<TextureCache>(); QSize framebufferSize = framebufferCache->getFrameBufferSize(); // binding the first framebuffer auto lightingFBO = framebufferCache->getLightingFramebuffer(); batch.setFramebuffer(lightingFBO); batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); // Bind the G-Buffer surfaces batch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, framebufferCache->getDeferredColorTexture()); batch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, framebufferCache->getDeferredNormalTexture()); batch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, framebufferCache->getDeferredSpecularTexture()); batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, framebufferCache->getPrimaryDepthTexture()); // FIXME: Different render modes should have different tasks if (args->_renderMode == RenderArgs::DEFAULT_RENDER_MODE && _ambientOcclusionEnabled) { batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, framebufferCache->getOcclusionTexture()); } else { // need to assign the white texture if ao is off batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, textureCache->getWhiteTexture()); } assert(_lightStage.lights.size() > 0); const auto& globalShadow = _lightStage.lights[0]->shadow; // Bind the shadow buffer batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow.map); // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport) auto monoViewport = args->_viewport; float sMin = args->_viewport.x / (float)framebufferSize.width(); float sWidth = args->_viewport.z / (float)framebufferSize.width(); float tMin = args->_viewport.y / (float)framebufferSize.height(); float tHeight = args->_viewport.w / (float)framebufferSize.height(); // The view frustum is the mono frustum base auto viewFrustum = args->_viewFrustum; // Eval the mono projection mat4 monoProjMat; viewFrustum->evalProjectionMatrix(monoProjMat); // The mono view transform Transform monoViewTransform; viewFrustum->evalViewTransform(monoViewTransform); // THe mono view matrix coming from the mono view transform glm::mat4 monoViewMat; monoViewTransform.getMatrix(monoViewMat); // Running in stero ? bool isStereo = args->_context->isStereo(); int numPasses = 1; mat4 projMats[2]; Transform viewTransforms[2]; ivec4 viewports[2]; vec4 clipQuad[2]; vec2 screenBottomLeftCorners[2]; vec2 screenTopRightCorners[2]; vec4 fetchTexcoordRects[2]; DeferredTransform deferredTransforms[2]; auto geometryCache = DependencyManager::get<GeometryCache>(); if (isStereo) { numPasses = 2; mat4 eyeViews[2]; args->_context->getStereoProjections(projMats); args->_context->getStereoViews(eyeViews); float halfWidth = 0.5f * sWidth; for (int i = 0; i < numPasses; i++) { // In stereo, the 2 sides are layout side by side in the mono viewport and their width is half int sideWidth = monoViewport.z >> 1; viewports[i] = ivec4(monoViewport.x + (i * sideWidth), monoViewport.y, sideWidth, monoViewport.w); deferredTransforms[i].projection = projMats[i]; auto sideViewMat = monoViewMat * glm::inverse(eyeViews[i]); viewTransforms[i].evalFromRawMatrix(sideViewMat); deferredTransforms[i].viewInverse = sideViewMat; deferredTransforms[i].stereoSide = (i == 0 ? -1.0f : 1.0f); clipQuad[i] = glm::vec4(sMin + i * halfWidth, tMin, halfWidth, tHeight); screenBottomLeftCorners[i] = glm::vec2(-1.0f + i * 1.0f, -1.0f); screenTopRightCorners[i] = glm::vec2(i * 1.0f, 1.0f); fetchTexcoordRects[i] = glm::vec4(sMin + i * halfWidth, tMin, halfWidth, tHeight); } } else { viewports[0] = monoViewport; projMats[0] = monoProjMat; deferredTransforms[0].projection = monoProjMat; deferredTransforms[0].viewInverse = monoViewMat; viewTransforms[0] = monoViewTransform; deferredTransforms[0].stereoSide = 0.0f; clipQuad[0] = glm::vec4(sMin, tMin, sWidth, tHeight); screenBottomLeftCorners[0] = glm::vec2(-1.0f, -1.0f); screenTopRightCorners[0] = glm::vec2(1.0f, 1.0f); fetchTexcoordRects[0] = glm::vec4(sMin, tMin, sWidth, tHeight); } auto eyePoint = viewFrustum->getPosition(); float nearRadius = glm::distance(eyePoint, viewFrustum->getNearTopLeft()); for (int side = 0; side < numPasses; side++) { // Render in this side's viewport batch.setViewportTransform(viewports[side]); batch.setStateScissorRect(viewports[side]); // Sync and Bind the correct DeferredTransform ubo _deferredTransformBuffer[side]._buffer->setSubData(0, sizeof(DeferredTransform), (const gpu::Byte*) &deferredTransforms[side]); batch.setUniformBuffer(_directionalLightLocations->deferredTransformBuffer, _deferredTransformBuffer[side]); glm::vec2 topLeft(-1.0f, -1.0f); glm::vec2 bottomRight(1.0f, 1.0f); glm::vec2 texCoordTopLeft(clipQuad[side].x, clipQuad[side].y); glm::vec2 texCoordBottomRight(clipQuad[side].x + clipQuad[side].z, clipQuad[side].y + clipQuad[side].w); // First Global directional light and ambient pass { auto& program = _shadowMapEnabled ? _directionalLightShadow : _directionalLight; LightLocationsPtr locations = _shadowMapEnabled ? _directionalLightShadowLocations : _directionalLightLocations; const auto& keyLight = _allocatedLights[_globalLights.front()]; // Setup the global directional pass pipeline { if (_shadowMapEnabled) { if (keyLight->getAmbientMap()) { program = _directionalSkyboxLightShadow; locations = _directionalSkyboxLightShadowLocations; } else { program = _directionalAmbientSphereLightShadow; locations = _directionalAmbientSphereLightShadowLocations; } } else { if (keyLight->getAmbientMap()) { program = _directionalSkyboxLight; locations = _directionalSkyboxLightLocations; } else { program = _directionalAmbientSphereLight; locations = _directionalAmbientSphereLightLocations; } } if (locations->shadowTransformBuffer >= 0) { batch.setUniformBuffer(locations->shadowTransformBuffer, globalShadow.getBuffer()); } batch.setPipeline(program); } { // Setup the global lighting setupKeyLightBatch(batch, locations->lightBufferUnit, SKYBOX_MAP_UNIT); } { batch.setModelTransform(Transform()); batch.setProjectionTransform(glm::mat4()); batch.setViewTransform(Transform()); glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); geometryCache->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color); } if (keyLight->getAmbientMap()) { batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr); } } auto texcoordMat = glm::mat4(); /* texcoordMat[0] = glm::vec4(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f); texcoordMat[1] = glm::vec4(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f); */ texcoordMat[0] = glm::vec4(fetchTexcoordRects[side].z / 2.0f, 0.0f, 0.0f, fetchTexcoordRects[side].x + fetchTexcoordRects[side].z / 2.0f); texcoordMat[1] = glm::vec4(0.0f, fetchTexcoordRects[side].w / 2.0f, 0.0f, fetchTexcoordRects[side].y + fetchTexcoordRects[side].w / 2.0f); texcoordMat[2] = glm::vec4(0.0f, 0.0f, 1.0f, 0.0f); texcoordMat[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; batch.setProjectionTransform(projMats[side]); batch.setViewTransform(viewTransforms[side]); // Splat Point lights if (!_pointLights.empty()) { batch.setPipeline(_pointLight); batch._glUniformMatrix4fv(_pointLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat)); for (auto lightID : _pointLights) { auto& light = _allocatedLights[lightID]; // IN DEBUG: light->setShowContour(true); batch.setUniformBuffer(_pointLightLocations->lightBufferUnit, light->getSchemaBuffer()); float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) { Transform model; model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f)); batch.setModelTransform(model); batch.setViewTransform(Transform()); batch.setProjectionTransform(glm::mat4()); glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color); batch.setProjectionTransform(projMats[side]); batch.setViewTransform(viewTransforms[side]); } else { Transform model; model.setTranslation(glm::vec3(light->getPosition().x, light->getPosition().y, light->getPosition().z)); batch.setModelTransform(model.postScale(expandedRadius)); batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); geometryCache->renderSphere(batch); } } } // Splat spot lights if (!_spotLights.empty()) { batch.setPipeline(_spotLight); batch._glUniformMatrix4fv(_spotLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat)); for (auto lightID : _spotLights) { auto light = _allocatedLights[lightID]; // IN DEBUG: light->setShowContour(true); batch.setUniformBuffer(_spotLightLocations->lightBufferUnit, light->getSchemaBuffer()); auto eyeLightPos = eyePoint - light->getPosition(); auto eyeHalfPlaneDistance = glm::dot(eyeLightPos, light->getDirection()); const float TANGENT_LENGTH_SCALE = 0.666f; glm::vec4 coneParam(light->getSpotAngleCosSin(), TANGENT_LENGTH_SCALE * tanf(0.5f * light->getSpotAngle()), 1.0f); float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION); // TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume, // we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working... if ((eyeHalfPlaneDistance > -nearRadius) && (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius)) { coneParam.w = 0.0f; batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); Transform model; model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f)); batch.setModelTransform(model); batch.setViewTransform(Transform()); batch.setProjectionTransform(glm::mat4()); glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color); batch.setProjectionTransform( projMats[side]); batch.setViewTransform(viewTransforms[side]); } else { coneParam.w = 1.0f; batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam)); Transform model; model.setTranslation(light->getPosition()); model.postRotate(light->getOrientation()); model.postScale(glm::vec3(expandedRadius, expandedRadius, expandedRadius)); batch.setModelTransform(model); auto mesh = getSpotLightMesh(); batch.setIndexBuffer(mesh->getIndexBuffer()); batch.setInputBuffer(0, mesh->getVertexBuffer()); batch.setInputFormat(mesh->getVertexFormat()); auto& part = mesh->getPartBuffer().get<model::Mesh::Part>(); batch.drawIndexed(model::Mesh::topologyToPrimitive(part._topology), part._numIndices, part._startIndex); } } } } // Probably not necessary in the long run because the gpu layer would unbound this texture if used as render target batch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, nullptr); batch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, nullptr); batch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, nullptr); batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, nullptr); batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, nullptr); batch.setResourceTexture(SHADOW_MAP_UNIT, nullptr); batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr); batch.setUniformBuffer(_directionalLightLocations->deferredTransformBuffer, nullptr); });
void VertexInfoFactory::convertVertexFormat( E_VERTEX_TYPE vertexType, u32* outVertexFormat, u32* outVertexSize ) { u32 vertexFormat = 0; u32 vertexSize = 0; switch ( vertexType ) { case EVT_VERTEX_P: vertexFormat = getVertexFormat( ( SVertexP* ) NULL ); vertexSize = sizeof( SVertexP ); break; case EVT_VERTEX_PC: vertexFormat = getVertexFormat( ( SVertexPC* ) NULL ); vertexSize = sizeof( SVertexPC ); break; case EVT_VERTEX_PT: vertexFormat = getVertexFormat( ( SVertexPT* ) NULL ); vertexSize = sizeof( SVertexPT ); break; case EVT_VERTEX_PTT: vertexFormat = getVertexFormat( ( SVertexPTT* ) NULL ); vertexSize = sizeof( SVertexPTT ); break; case EVT_VERTEX_PCT: vertexFormat = getVertexFormat( ( SVertexPCT* ) NULL ); vertexSize = sizeof( SVertexPCT ); break; case EVT_VERTEX_PN: vertexFormat = getVertexFormat( ( SVertexPN* ) NULL ); vertexSize = sizeof( SVertexPN ); break; case EVT_VERTEX_PNT: vertexFormat = getVertexFormat( ( SVertexPNT* ) NULL ); vertexSize = sizeof( SVertexPNT ); break; case EVT_VERTEX_PNTT: vertexFormat = getVertexFormat( ( SVertexPNTT* ) NULL ); vertexSize = sizeof( SVertexPNTT ); break; case EVT_VERTEX_PTTT: vertexFormat = getVertexFormat( ( SVertexPTTT* ) NULL ); vertexSize = sizeof( SVertexPTTT ); break; case EVT_VERTEX_PNTTGB: vertexFormat = getVertexFormat( ( SVertexPNTTGB* ) NULL ); vertexSize = sizeof( SVertexPNTTGB ); break; } *outVertexFormat = vertexFormat; *outVertexSize = vertexSize; }