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()); } }
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) { 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; }
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 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(); }