void Storm3D_Spotlight::testVisibility(Storm3D_Camera &camera) { // Simple hack, skip visibility check if camera has orthogonal projection on (practically when mapview is enabled) if(!(data->spotlightAlwaysVisible || camera.GetForcedOrthogonalProjectionEnabled() ) ) { data->visible = camera.TestSphereVisibility(data->properties.position, data->properties.range); data->coneUpdated = false; } else { data->visible = true; data->coneUpdated = false; } }
void updateMatrices(const float *cameraView) { float bias = getBias(); if(shadowMap) properties.targetPos = shadowMap->pos; properties.resolutionX = 2 * SHADOW_WIDTH; properties.resolutionY = 2 * SHADOW_HEIGHT; properties.updateMatrices(cameraView, bias); camera.SetPosition(properties.position); camera.SetTarget(properties.position + properties.direction); camera.SetFieldOfView(D3DXToRadian(properties.fov)); camera.SetVisibilityRange(properties.range); }
void findDecals(Storm3D_Scene &scene) { decals.clear(); // Find decals { IStorm3D_Camera *camera = scene.GetCamera(); Storm3D_Camera *stormCamera = reinterpret_cast<Storm3D_Camera *> (camera); Frustum frustum = stormCamera->getFrustum(); Tree::FrustumIterator itf(*tree, frustum); for(; !itf.end(); itf.next()) decals.push_back(*itf); std::sort(decals.begin(), decals.end(), DecalSorter()); } }
/*! \param camera camera to which test visibility */ void Storm3D_FakeSpotlight::testVisibility(Storm3D_Camera &camera) { // data->visible = camera.TestSphereVisibility(data->properties.position, data->properties.range); // data->visible = true; // Frustum vs. AABB VC2 min, max; float planeY = data->properties.position.y - data->plane.height; getPlane(min, max); AABB clipBox ( VC3( min.x, planeY - 0.1f, min.y ), VC3( max.x, planeY + 0.1f, max.y ) ); data->visible = camera.TestBoxVisibility ( clipBox.mmin, clipBox.mmax ); }
void renderShadows(Storm3D_Scene &scene) { // this is BROKEN // FIXME // just clear the list shadowDecals.clear(); return; createIndexBuffers(); int renderAmount = 0; if(!shadowDecals.empty()) { IStorm3D_Camera *camera = scene.GetCamera(); Storm3D_Camera *stormCamera = reinterpret_cast<Storm3D_Camera *> (camera); Frustum frustum = stormCamera->getFrustum(); shadowVertices.create(shadowDecals.size() * 4, VERTEX_SIZE, true); int rawSize = shadowDecals.size() * 4 * VERTEX_SIZE; void *ramBuffer = malloc(rawSize); void *lockPointer = shadowVertices.lock(); VXFORMAT_DECAL *buffer = reinterpret_cast<VXFORMAT_DECAL *> (ramBuffer); float inverseRange =1.f / fogRange; for(unsigned int i = 0; i < shadowDecals.size(); ++i) { const StormDecal &decal = shadowDecals[i]; Sphere sphere(decal.position, decal.getRadius()); if(frustum.visibility(sphere)) { float factor = decal.position.y - fogEnd; factor *= inverseRange; if(factor < 0.f) factor = 0.f; if(factor > 1.f) factor = 1.f; factor = 1.f - factor; COL color = decal.light; color.r += factor * (1.f - color.r); color.g += factor * (1.f - color.g); color.b += factor * (1.f - color.b); DWORD vertexColor = color.GetAsD3DCompatibleARGB() & 0x00FFFFFF; DWORD oldColor = decal.vertexColor; decal.vertexColor = vertexColor; decal.insert(buffer); decal.vertexColor = oldColor; buffer += 4; ++renderAmount; } } if(renderAmount) { if(renderAmount > STORM_MAX_DECAL_AMOUNT) renderAmount = STORM_MAX_DECAL_AMOUNT; memcpy(lockPointer, ramBuffer, renderAmount * 4 * VERTEX_SIZE); } free(ramBuffer); shadowVertices.unlock(); } D3DXMATRIX tm; frozenbyte::storm::VertexShader::disable(); frozenbyte::storm::PixelShader::disable(); Storm3D_ShaderManager::GetSingleton()->SetWorldTransform(tm); applyFVF(DECAL_FVF, VERTEX_SIZE); glActiveTexture(GL_TEXTURE0); glClientActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glActiveTexture(GL_TEXTURE1); glClientActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_3D); glDisable(GL_TEXTURE_CUBE_MAP); glDepthMask(GL_FALSE); glEnable(GL_BLEND); glDisable(GL_ALPHA_TEST); glBlendFunc(GL_ZERO, GL_SRC_COLOR); if(renderAmount && shadowMaterial) { shadowVertices.apply(0); shadowMaterial->applyShadow(); indices.render(renderAmount * 2, renderAmount * 4); scene.AddPolyCounter(renderAmount * 2); } glDepthMask(GL_TRUE); glDisable(GL_BLEND); shadowDecals.clear(); }
bool Storm3D_SpotlightShared::setScissorRect(Storm3D_Camera &camera, const VC2I &screenSize, Storm3D_Scene *scene) { D3DXMATRIX light; D3DXVECTOR3 lightPosition(position.x, position.y, position.z); D3DXVECTOR3 up(0, 1.f, 0); D3DXVECTOR3 lookAt = lightPosition; lookAt += D3DXVECTOR3(direction.x, direction.y, direction.z); D3DXMatrixLookAtLH(&light, &lightPosition, &lookAt, &up); // Create frustum vertices D3DXVECTOR3 v[5]; v[0] = D3DXVECTOR3(0, 0, 0); v[1] = D3DXVECTOR3(0, 0, 1.f); v[2] = D3DXVECTOR3(0, 0, 1.f); v[3] = D3DXVECTOR3(0, 0, 1.f); v[4] = D3DXVECTOR3(0, 0, 1.f); float det = D3DXMatrixDeterminant(&light); D3DXMatrixInverse(&light, &det, &light); float angle = D3DXToRadian(fov) * .5f; for(int i = 0; i <= 4; ++i) { if(i > 0) { float z = v[i].z; if(i == 1 || i == 2) { v[i].x = z * sinf(angle); v[i].z = z * cosf(angle); } else { v[i].x = z * sinf(-angle); v[i].z = z * cosf(-angle); } if(i == 1 || i == 3) v[i].y = z * sinf(angle); else v[i].y = z * sinf(-angle); float scale = range / cosf(angle); v[i] *= scale; } D3DXVec3TransformCoord(&v[i], &v[i], &light); } // Create area const Frustum &frustum = camera.getFrustum(); int minX = screenSize.x; int minY = screenSize.y; int maxX = 0; int maxY = 0; for(int i = 0; i < 6; ++i) { VC3 v1; VC3 v2; VC3 v3; if(i == 0) { v1 = toVC3(v[0]); v2 = toVC3(v[1]); v3 = toVC3(v[2]); } else if(i == 1) { v1 = toVC3(v[0]); v2 = toVC3(v[2]); v3 = toVC3(v[4]); } else if(i == 2) { v1 = toVC3(v[0]); v2 = toVC3(v[3]); v3 = toVC3(v[4]); } else if(i == 3) { v1 = toVC3(v[0]); v2 = toVC3(v[1]); v3 = toVC3(v[3]); } else if(i == 4) { v1 = toVC3(v[1]); v2 = toVC3(v[2]); v3 = toVC3(v[3]); } else if(i == 5) { v1 = toVC3(v[4]); v2 = toVC3(v[2]); v3 = toVC3(v[3]); } const ClipPolygon &clipPolygon = clipTriangleToFrustum(v1, v2, v3, frustum); for(int j = 0; j < clipPolygon.vertexAmount; ++j) { VC3 result; float rhw = 0.f; float real_z = 0.f; camera.GetTransformedToScreen(clipPolygon.vertices[j], result, rhw, real_z); int x = int(result.x * screenSize.x); int y = int(result.y * screenSize.y); //if(x < -1 || x > screenSize.x) // continue; //if(y < -1 || x > screenSize.y) // continue; x = max(x, 0); y = max(y, 0); x = min(x, screenSize.x - 1); y = min(y, screenSize.y - 1); maxX = max(x, maxX); maxY = max(y, maxY); minX = min(x, minX); minY = min(y, minY); /* // Visualize clipped polygons if(scene) { VC3 p1 = clipPolygon.vertices[j]; VC3 p2 = clipPolygon.vertices[(j + 1) % clipPolygon.vertexAmount]; for(int k = 0; k < 5; ++k) { const VC3 &planeNormal = frustum.planeNormals[k]; PLANE plane; if(k == 0) plane.MakeFromNormalAndPosition(planeNormal, frustum.position + planeNormal); else plane.MakeFromNormalAndPosition(planeNormal, frustum.position); float d1 = plane.GetPointRange(p1); float d2 = plane.GetPointRange(p2); if(d1 < .25f) p1 += planeNormal * (.25f - d1); if(d2 < .25f) p2 += planeNormal * (.25f - d2); } scene->AddLine(p1, p2, COL(1.f, 1.f, 1.f)); } */ } } RECT rc; bool visible = false; if(maxX > minX && maxY > minY) { visible = true; rc.left = minX; rc.top = minY; rc.right = maxX; rc.bottom = maxY; } else { visible = false; rc.left = 0; rc.top = 0; rc.right = 1; rc.bottom = 1; } /* // Visualize scissor area if(scene && visible) { static DWORD foo = GetTickCount(); int dif = (GetTickCount() - foo) % 2000; if(dif < 1000) scene->Render2D_Picture(0, VC2(float(minX), float(minY)), VC2(float(maxX - minX), float(maxY - minY)), 0.5f, 0.f, 0, 0, 0, 0, false); } */ device.SetScissorRect(&rc); device.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); return visible; }
void Storm3D_SpotlightShared::updateMatricesOffCenter(const D3DXMATRIX &cameraView, const VC2 &min, const VC2 &max, float height, Storm3D_Camera &camera) { // Position of the light in global coordinates // Y-axis is height D3DXVECTOR3 lightPosition(position.x, position.y, position.z); // Up vector (z-axis) D3DXVECTOR3 up(0.f, 0.f, 1.f); // Look direction D3DXVECTOR3 lookAt = lightPosition; lookAt.y -= 1.f; { // max and min define the extents of light area in local coordinates // Z-axis is height float zmin = 0.2f; //float zmax = std::max(range, height) * 1.4f; // height is light height from light properties float zmax = height; float factor = 1.5f * zmin / height; float xmin = min.x * factor; float xmax = max.x * factor; float ymin = min.y * factor; float ymax = max.y * factor; D3DXMatrixPerspectiveOffCenterLH(&lightProjection, xmin, xmax, ymin, ymax, zmin, zmax); // Calculate the extents of light area in global coordinates VC2 worldMin = min; worldMin.x += position.x; worldMin.y += position.z; VC2 worldMax = max; worldMax.x += position.x; worldMax.y += position.z; // Generate approximate camera for culling. // Calculate range of the camera. // Y-axis is height float planeY = position.y - height; // Calculate distances from light position to light plane edges VC3 p1 = VC3( worldMin.x, planeY, worldMin.y ) - position; VC3 p2 = VC3( worldMax.x, planeY, worldMin.y ) - position; VC3 p3 = VC3( worldMax.x, planeY, worldMax.y ) - position; VC3 p4 = VC3( worldMin.x, planeY, worldMax.y ) - position; float d1 = p1.GetLength(); float d2 = p2.GetLength(); float d3 = p3.GetLength(); float d4 = p4.GetLength(); float maxRange = 0.0f; maxRange = MAX( maxRange, d1 ); maxRange = MAX( maxRange, d2 ); maxRange = MAX( maxRange, d3 ); maxRange = MAX( maxRange, d4 ); //maxRange = sqrtf(maxRange); // Calculate FOV of the camera. VC3 planeCenter = VC3( (worldMin.x + worldMax.x) * 0.5f, planeY, (worldMin.y + worldMax.y) * 0.5f ); VC3 camVec = planeCenter - position; camVec.Normalize(); float minDot = 10000.0f; float t1 = camVec.GetDotWith( p1 ) / d1; float t2 = camVec.GetDotWith( p2 ) / d2; float t3 = camVec.GetDotWith( p3 ) / d3; float t4 = camVec.GetDotWith( p4 ) / d4; minDot = MIN( minDot, t1 ); minDot = MIN( minDot, t2 ); minDot = MIN( minDot, t3 ); minDot = MIN( minDot, t4 ); float maxAngle = acosf( minDot ); // Place camera to light position camera.SetPosition(position); camera.SetUpVec(VC3(0.f, 0.f, 1.f)); // Point camera at light plane center camera.SetTarget(planeCenter); camera.SetFieldOfView( maxAngle ); camera.SetVisibilityRange( maxRange ); } D3DXMATRIX cameraMatrix(cameraView); float det = D3DXMatrixDeterminant(&cameraMatrix); D3DXMatrixInverse(&cameraMatrix, &det, &cameraMatrix); unsigned int tweakRange = 1; float bias = 0.f; float currentBias = 0.f; for(int i = 0; i < 2; ++i) { D3DXMatrixLookAtLH(&lightView[i], &lightPosition, &lookAt, &up); if(i == 1) currentBias = 0; // Tweak matrix float soffsetX = 0.5f; float soffsetY = 0.5f; float scale = 0.5f; D3DXMATRIX shadowTweak( scale, 0.0f, 0.0f, 0.0f, 0.0f, -scale, 0.0f, 0.0f, 0.0f, 0.0f, float(tweakRange), 0.0f, soffsetX, soffsetY, currentBias, 1.0f ); D3DXMatrixMultiply(&shadowProjection[i], &lightProjection, &shadowTweak); D3DXMatrixMultiply(&shadowProjection[i], &lightView[i], &shadowProjection[i]); D3DXMatrixMultiply(&lightViewProjection[i], &lightView[i], &lightProjection); shaderProjection[i] = shadowProjection[i]; D3DXMatrixMultiply(&shadowProjection[i], &cameraMatrix, &shadowProjection[i]); } { float xf = (1.f / resolutionX * .5f); float yf = (1.f / resolutionY * .5f); float sX = soffsetX + (2 * targetPos.x * soffsetX) - xf; float sY = soffsetY + (2 * targetPos.y * soffsetY) - yf; D3DXMATRIX shadowTweak( scaleX, 0.0f, 0.0f, 0.0f, 0.0f, -scaleY, 0.0f, 0.0f, 0.0f, 0.0f, float(tweakRange), 0.0f, sX, sY, bias, 1.0f ); D3DXMatrixMultiply(&targetProjection, &lightProjection, &shadowTweak); D3DXMatrixMultiply(&targetProjection, &lightView[0], &targetProjection); } }
/*! \param present \return polygon count */ int Storm3D_Scene::RenderScene(bool present) { // Reset polygon counter poly_counter = 0; { static int haxValue = 0; ++haxValue; IStorm3D_Texture *target = Storm3D2->getReflectionTexture(); if(target /*&& haxValue > 1*/) { haxValue = 0; enableLocalReflection = true; frozenbyte::storm::setInverseCulling(true); active_visibility = 1; Storm3D_Camera camback = camera; camback.Apply(); Storm3D_Texture *render_target = (Storm3D_Texture *) target; if (!render_target->IsCube()) { bool renderHalved = true; bool renderDistortion = true; bool renderGlow = true; bool renderGlowImproved = true; bool renderFakes = true; bool renderFakeShadows = true; bool renderSpotShadows = true; bool renderParticles = true; if(!terrains.empty()) { IStorm3D_TerrainRenderer &renderer = (*terrains.begin())->getRenderer(); bool shouldRenderHalved = Storm3D2->halfReflection; bool shouldRenderDistortion = false; bool shouldRenderGlow = false; bool shouldRenderGlowImproved = false; bool shouldRenderFakes = false; bool shouldRenderFakeShadows = false; bool shouldRenderSpotShadows = false; // Particle reflection hacky bool shouldRenderParticleReflection = false; shouldRenderParticleReflection = renderer.enableFeature(IStorm3D_TerrainRenderer::ParticleReflection, false); renderer.enableFeature(IStorm3D_TerrainRenderer::ParticleReflection, shouldRenderParticleReflection); renderParticles = renderer.enableFeature(IStorm3D_TerrainRenderer::Particles, shouldRenderParticleReflection); if(Storm3D2->reflectionQuality >= 100) { shouldRenderDistortion = true; shouldRenderGlow = true; } renderHalved = renderer.enableFeature(IStorm3D_TerrainRenderer::HalfRendering, shouldRenderHalved); renderDistortion = renderer.enableFeature(IStorm3D_TerrainRenderer::Distortion, shouldRenderDistortion); renderGlow = renderer.enableFeature(IStorm3D_TerrainRenderer::Glow, shouldRenderGlow); renderGlowImproved = renderer.enableFeature(IStorm3D_TerrainRenderer::BetterGlowSampling, shouldRenderGlowImproved); renderFakes = renderer.enableFeature(IStorm3D_TerrainRenderer::FakeLights, shouldRenderFakes); renderFakeShadows = renderer.enableFeature(IStorm3D_TerrainRenderer::FakeShadows, shouldRenderFakeShadows); renderSpotShadows = renderer.enableFeature(IStorm3D_TerrainRenderer::SpotShadows, shouldRenderSpotShadows); // If we already have features disabled, don't enable them for reflection if(renderHalved) renderer.enableFeature(IStorm3D_TerrainRenderer::HalfRendering, true); if(!renderDistortion) renderer.enableFeature(IStorm3D_TerrainRenderer::Distortion, false); if(!renderGlowImproved) renderer.enableFeature(IStorm3D_TerrainRenderer::BetterGlowSampling, false); if(!renderGlow) renderer.enableFeature(IStorm3D_TerrainRenderer::Glow, false); if(!renderFakes) renderer.enableFeature(IStorm3D_TerrainRenderer::FakeLights, false); if(!renderFakeShadows) renderer.enableFeature(IStorm3D_TerrainRenderer::FakeShadows, false); if(!renderSpotShadows) renderer.enableFeature(IStorm3D_TerrainRenderer::SpotShadows, false); } VC3 position = camera.GetPosition(); VC3 target = camera.GetTarget(); // Mirror relative to reflection plane position.y = reflection_height - (position.y - reflection_height); target.y = reflection_height - (target.y - reflection_height); camera.SetPosition(position); camera.SetTarget(target); camera.ForceViewProjection(&camback); RenderSceneWithParams(false,false,false,true,render_target); igios_unimplemented(); if(!terrains.empty()) { IStorm3D_TerrainRenderer &renderer = (*terrains.begin())->getRenderer(); renderer.enableFeature(IStorm3D_TerrainRenderer::HalfRendering, renderHalved); renderer.enableFeature(IStorm3D_TerrainRenderer::Distortion, renderDistortion); renderer.enableFeature(IStorm3D_TerrainRenderer::Glow, renderGlow); renderer.enableFeature(IStorm3D_TerrainRenderer::BetterGlowSampling, renderGlowImproved); renderer.enableFeature(IStorm3D_TerrainRenderer::FakeLights, renderFakes); renderer.enableFeature(IStorm3D_TerrainRenderer::FakeShadows, renderFakeShadows); renderer.enableFeature(IStorm3D_TerrainRenderer::SpotShadows, renderSpotShadows); renderer.enableFeature(IStorm3D_TerrainRenderer::Particles, renderParticles); } // debugging code if(false){ static IStorm3D_Material *hax = this->Storm3D2->CreateNewMaterial(".."); hax->SetBaseTexture(render_target); this->Render2D_Picture(hax, VC2(300,10), VC2(512,512), 1.f, 0.f, 0.f, 0.f, 1.f, 1.f, false); } } active_visibility = 0; enableLocalReflection = false; frozenbyte::storm::setInverseCulling(false); camera = camback; } } // Render with flip RenderSceneWithParams(present, false); // Return polygon count return poly_counter; }
bool Storm3D_SpotlightShared::setScissorRect(Storm3D_Camera &camera, const VC2I &screenSize) { D3DXMATRIX light; D3DXVECTOR3 lightPosition(position.x, position.y, position.z); D3DXVECTOR3 up(0, 1.f, 0); D3DXVECTOR3 lookAt = lightPosition; lookAt += D3DXVECTOR3(direction.x, direction.y, direction.z); D3DXMatrixLookAtLH(&light, &lightPosition, &lookAt, &up); D3DXVECTOR3 v[5]; v[0] = D3DXVECTOR3(0, 0, 0); v[1] = D3DXVECTOR3(0, 0, 1.f); v[2] = D3DXVECTOR3(0, 0, 1.f); v[3] = D3DXVECTOR3(0, 0, 1.f); v[4] = D3DXVECTOR3(0, 0, 1.f); int minX = screenSize.x; int minY = screenSize.y; int maxX = 0; int maxY = 0; float det = D3DXMatrixDeterminant(&light); D3DXMatrixInverse(&light, &det, &light); float angle = D3DXToRadian(fov) * .5f; for(int i = 0; i <= 4; ++i) { if(i > 0) { float z = v[i].z; if(i == 1 || i == 2) { v[i].x = z * sinf(angle); v[i].z = z * cosf(angle); } else { v[i].x = z * sinf(-angle); v[i].z = z * cosf(-angle); } if(i == 1 || i == 3) v[i].y = z * sinf(angle); else v[i].y = z * sinf(-angle); float scale = range / cosf(angle); v[i] *= scale; } D3DXVec3TransformCoord(&v[i], &v[i], &light); } const Frustum &frustum = camera.getFrustum(); calculateLineToScissor(toVC3(v[0]), toVC3(v[1]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[0]), toVC3(v[2]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[0]), toVC3(v[3]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[0]), toVC3(v[4]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[1]), toVC3(v[2]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[2]), toVC3(v[3]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[3]), toVC3(v[4]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[4]), toVC3(v[1]), frustum, camera, screenSize, minX, minY, maxX, maxY); /* VC3 cameraPos = camera.GetPosition(); VC3 cameraPosResult; float cameraRhw = 0, cameraRealZ = 0; bool cameraVisible = camera.GetTransformedToScreen(cameraPos, cameraPosResult, cameraRhw, cameraRealZ); for(i = 0; i <= 4; ++i) { VC3 source(v[i].x, v[i].y, v[i].z); VC3 result; float rhw = 0, realZ = 0; bool inFront = camera.GetTransformedToScreen(source, result, rhw, realZ); // HAX HAX! result.x = std::max(0.f, result.x); result.y = std::max(0.f, result.y); result.x = std::min(1.f, result.x); result.y = std::min(1.f, result.y); //if(fabsf(rhw) < 0.0001f) // continue; bool flip = false; if(realZ < cameraRealZ) flip = true; if(flip) { result.x = 1.f - result.x; result.y = 1.f - result.y; //minX = 0; //minY = 0; //maxX = screenSize.x; //maxY = screenSize.y; } int x = int(result.x * screenSize.x); int y = int(result.y * screenSize.y); maxX = std::max(x, maxX); maxY = std::max(y, maxY); minX = std::min(x, minX); minY = std::min(y, minY); } */ if(maxX > screenSize.x) maxX = screenSize.x; if(maxY > screenSize.y) maxY = screenSize.y; if(minX < 0) minX = 0; if(minY < 0) minY = 0; RECT rc; rc.left = minX; rc.top = minY; rc.right = maxX; rc.bottom = maxY; if(rc.left < rc.right && rc.top < rc.bottom) { device.SetScissorRect(&rc); device.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); } else { RECT rc; rc.left = 0; rc.top = 0; rc.right = 1; rc.bottom = 1; device.SetScissorRect(&rc); device.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); return false; } return true; }
void Storm3D_Spotlight::renderCone(Storm3D_Camera &camera, float timeFactor, bool renderGlows) { if(!data->hasCone || !data->hasShadows || !data->shadowMap) return; bool normalPass = !data->coneUpdated; if(data->hasCone && data->updateCone && !data->coneUpdated) { data->createCone(); data->coneUpdated = true; } D3DXVECTOR3 lightPosition(data->properties.position.x, data->properties.position.y, data->properties.position.z); D3DXVECTOR3 up(0, 1.f, 0); D3DXVECTOR3 lookAt = lightPosition; lookAt += D3DXVECTOR3(data->properties.direction.x, data->properties.direction.y, data->properties.direction.z); D3DXMATRIX tm; D3DXMatrixLookAtLH(&tm, &lightPosition, &lookAt, &up); VC3 cameraDir = camera.GetDirection(); cameraDir.Normalize(); D3DXVECTOR3 direction(cameraDir.x, cameraDir.y, cameraDir.z); D3DXVec3TransformNormal(&direction, &direction, &tm); Storm3D_ShaderManager::GetSingleton()->setSpot(data->properties.color, data->properties.position, data->properties.direction, data->properties.range, .1f); Storm3D_ShaderManager::GetSingleton()->setTextureTm(data->properties.shaderProjection[0]); Storm3D_ShaderManager::GetSingleton()->setSpotTarget(data->properties.targetProjection); float det = D3DXMatrixDeterminant(&tm); D3DXMatrixInverse(&tm, &det, &tm); Storm3D_ShaderManager::GetSingleton()->SetWorldTransform(data->device, tm, true); if(data->shadowMap && data->shadowMap->hasInitialized()) data->shadowMap->apply(0); if(data->coneTexture) { data->coneTexture->AnimateVideo(); data->coneTexture->Apply(3); if(type == AtiBuffer || type == AtiFloatBuffer) data->coneTexture->Apply(4); else data->coneTexture->Apply(1); } if(type == AtiBuffer) { if(data->coneTexture) data->coneAtiPixelShader_Texture->apply(); else data->coneAtiPixelShader_NoTexture->apply(); } else if(type == AtiFloatBuffer) { if(data->coneTexture) data->coneAtiFloatPixelShader_Texture->apply(); else data->coneAtiFloatPixelShader_NoTexture->apply(); } else { if(data->coneTexture) data->coneNvPixelShader_Texture->apply(); else data->coneNvPixelShader_NoTexture->apply(); } float colorMul = data->coneColorMultiplier; float colorData[4] = { data->properties.color.r * colorMul, data->properties.color.g * colorMul, data->properties.color.b * colorMul, 1.f }; if(renderGlows) { if(normalPass) { colorData[0] *= 0.2f; colorData[1] *= 0.2f; colorData[2] *= 0.2f; colorData[3] *= 0.2f; } else { colorData[0] *= 0.4f; colorData[1] *= 0.4f; colorData[2] *= 0.4f; colorData[3] *= 0.4f; } } data->device.SetVertexShaderConstantF(9, colorData, 1); float bias = 0.005f; float directionData[4] = { -direction.x, -direction.y, -direction.z, bias }; data->device.SetVertexShaderConstantF(10, directionData, 1); for(int i = 0; i < 2; ++i) { data->angle[i] += data->speed[i] * timeFactor; D3DXVECTOR3 center(0.5f, 0.5f, 0.f); D3DXQUATERNION quat1; D3DXQuaternionRotationYawPitchRoll(&quat1, 0, 0, data->angle[i]); D3DXMATRIX rot1; D3DXMatrixAffineTransformation(&rot1, 1.f, ¢er, &quat1, 0); D3DXMatrixTranspose(&rot1, &rot1); if(i == 0) data->device.SetVertexShaderConstantF(16, rot1, 3); else data->device.SetVertexShaderConstantF(19, rot1, 3); } frozenbyte::storm::enableMipFiltering(data->device, 0, 0, false); data->coneVertexBuffer.apply(data->device, 0); data->coneIndexBuffer.render(data->device, CONE_FACES, CONE_VERTICES); frozenbyte::storm::enableMipFiltering(data->device, 0, 0, true); }
void renderShadows(Storm3D_Scene &scene) { gfx::Renderer& renderer = storm.renderer; gfx::Device& device = renderer.device; gfx::ProgramManager& programManager = renderer.programManager; if (shadowDecals.empty() || !shadowMaterial) return; int renderAmount = 0; IStorm3D_Camera *camera = scene.GetCamera(); Storm3D_Camera *stormCamera = reinterpret_cast<Storm3D_Camera *> (camera); Frustum frustum = stormCamera->getFrustum(); uint32_t baseVertex = 0; Vertex_P3DUV *buffer = 0;; renderer.lockDynVtx<Vertex_P3DUV>(shadowDecals.size() * 4, &buffer, &baseVertex); float inverseRange = 1.f / fogRange; for (unsigned int i = 0; i < shadowDecals.size() && renderAmount < MAX_DECAL_AMOUNT; ++i) { const Decal &decal = shadowDecals[i]; Sphere sphere(decal.position, decal.getRadius()); if (frustum.visibility(sphere)) { float factor = decal.position.y - fogEnd; factor *= inverseRange; factor = std::max(0.0f, factor); factor = std::min(1.0f, factor); factor = 1.f - factor; COL color = decal.light; color.r += factor * (1.f - color.r); color.g += factor * (1.f - color.g); color.b += factor * (1.f - color.b); uint32_t vertexColor = color.as_u32_D3D_ARGB(decal.alpha); decal.insert(buffer, vertexColor); buffer += 4; ++renderAmount; } } renderer.unlockDynVtx(); if (renderAmount == 0) return; D3DXMATRIX tm; D3DXMatrixIdentity(&tm); programManager.setProgram( gfx::ProgramManager::DECAL_SHADOW); programManager.setWorldMatrix(tm); programManager.applyState(device); device.SetRenderState(D3DRS_ZWRITEENABLE, FALSE); device.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); device.SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR); if (shadowMaterial->baseTexture) shadowMaterial->baseTexture->Apply(0); renderer.setFVF(FVF_P3DUV); renderer.setDynVtxBuffer<Vertex_P3DUV>(); renderer.drawQuads(baseVertex, renderAmount); device.SetRenderState(D3DRS_ZWRITEENABLE, TRUE); device.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); shadowDecals.clear(); }