void EERIEDrawBitmapUVs(Rectf rect, float z, TextureContainer * tex, Color color, Vec2f uv0, Vec2f uv1, Vec2f uv2, Vec2f uv3) { rect.move(-.5f, -.5f); ColorRGBA col = color.toRGBA(); TexturedVertex v[4]; v[0] = TexturedVertex(Vec3f(rect.topLeft(), z), 1.f, col, uv0); v[1] = TexturedVertex(Vec3f(rect.topRight(), z), 1.f, col, uv1); v[2] = TexturedVertex(Vec3f(rect.bottomLeft(), z), 1.f, col, uv2); v[3] = TexturedVertex(Vec3f(rect.bottomRight(), z), 1.f, col, uv3); SetTextureDrawPrim(tex, v, Renderer::TriangleStrip); }
void EERIEDrawBitmap_uv(Rectf rect, float z, TextureContainer * tex, Color color, float u0, float v0, float u1, float v1) { rect.move(-.5f, -.5f); Vec2f uv = (tex) ? tex->uv : Vec2f_ONE; u0 *= uv.x, u1 *= uv.x, v0 *= uv.y, v1 *= uv.y; ColorRGBA col = color.toRGBA(); TexturedVertex v[4]; v[0] = TexturedVertex(Vec3f(rect.topLeft(), z), 1.f, col, Vec2f(u0, v0)); v[1] = TexturedVertex(Vec3f(rect.topRight(), z), 1.f, col, Vec2f(u1, v0)); v[2] = TexturedVertex(Vec3f(rect.bottomRight(), z), 1.f, col, Vec2f(u1, v1)); v[3] = TexturedVertex(Vec3f(rect.bottomLeft(), z), 1.f, col, Vec2f(u0, v1)); SetTextureDrawPrim(tex, v, Renderer::TriangleFan); }
void CreateBitmap(TexturedQuad& s, Rectf rect, float z, TextureContainer * tex, Color color, bool isRhw) { rect.move(-.5f, -.5f); Vec2f uv = (tex) ? tex->uv : Vec2f_ZERO; ColorRGBA col = color.toRGBA(); float val = 1.f; if(isRhw) { val -= z; } s.v[0] = TexturedVertex(Vec3f(rect.topLeft(), z), val, col, Vec2f(0.f, 0.f)); s.v[1] = TexturedVertex(Vec3f(rect.topRight(), z), val, col, Vec2f(uv.x, 0.f)); s.v[2] = TexturedVertex(Vec3f(rect.bottomRight(), z), val, col, Vec2f(uv.x, uv.y)); s.v[3] = TexturedVertex(Vec3f(rect.bottomLeft(), z), val, col, Vec2f(0.f, uv.y)); }
void EERIEDrawBitmap2DecalY(Rectf rect, float z, TextureContainer * tex, Color color, float _fDeltaY) { rect.move(-.5f, -.5f); rect.top = rect.top + _fDeltaY * rect.height(); Vec2f uv = (tex) ? tex->uv : Vec2f_ZERO; float sv = uv.y * _fDeltaY; ColorRGBA col = color.toRGBA(); Vec2f uv1(0.f, sv); Vec2f uv2(uv.x, sv); Vec2f uv3(uv.x, uv.y); Vec2f uv4(0.f, uv.y); TexturedVertex v[4]; v[0] = TexturedVertex(Vec3f(rect.topLeft(), z), 1.f, col, uv1); v[1] = TexturedVertex(Vec3f(rect.topRight(), z), 1.f, col, uv2); v[2] = TexturedVertex(Vec3f(rect.bottomRight(), z), 1.f, col, uv3); v[3] = TexturedVertex(Vec3f(rect.bottomLeft(), z), 1.f, col, uv4); SetTextureDrawPrim(tex, v, Renderer::TriangleFan); }
void ARXDRAW_DrawInterShadows() { ARX_PROFILE_FUNC(); g_shadowBatch.clear(); GRenderer->SetFogColor(Color::none); GRenderer->SetDepthBias(1); for(long i=0; i<TREATZONE_CUR; i++) { if(treatio[i].show != 1 || !treatio[i].io) continue; Entity *io = treatio[i].io; if( !io->obj || (io->ioflags & IO_JUST_COLLIDE) || (io->ioflags & IO_NOSHADOW) || (io->ioflags & IO_GOLD) || !(io->show == SHOW_FLAG_IN_SCENE) ) { continue; } EERIE_BKG_INFO * bkgData = getFastBackgroundData(io->pos.x, io->pos.z); if(bkgData && !bkgData->treat) { //TODO is that correct ? continue; } TexturedVertex ltv[4]; ltv[0] = TexturedVertex(Vec3f(0, 0, 0.001f), 1.f, ColorRGBA(0), Vec2f(0.3f, 0.3f)); ltv[1] = TexturedVertex(Vec3f(0, 0, 0.001f), 1.f, ColorRGBA(0), Vec2f(0.7f, 0.3f)); ltv[2] = TexturedVertex(Vec3f(0, 0, 0.001f), 1.f, ColorRGBA(0), Vec2f(0.7f, 0.7f)); ltv[3] = TexturedVertex(Vec3f(0, 0, 0.001f), 1.f, ColorRGBA(0), Vec2f(0.3f, 0.7f)); if(io->obj->grouplist.size() <= 1) { for(size_t k = 0; k < io->obj->vertexlist.size(); k += 9) { EERIEPOLY *ep = CheckInPoly(io->obj->vertexlist3[k].v); if(!ep) continue; Vec3f in; in.y = ep->min.y - 3.f; float r = 0.5f - ((float)glm::abs(io->obj->vertexlist3[k].v.y - in.y)) * (1.f/500); r -= io->invisibility; r *= io->scale; if(r <= 0.f) continue; float s1 = 16.f * io->scale; float s2 = s1 * (1.f/2); in.x = io->obj->vertexlist3[k].v.x - s2; in.z = io->obj->vertexlist3[k].v.z - s2; r *= 255.f; long lv = r; ltv[0].color = ltv[1].color = ltv[2].color = ltv[3].color = Color(lv, lv, lv, 255).toRGBA(); ltv[0].p = EE_RT(in); in.x += s1; ltv[1].p = EE_RT(in); in.z += s1; ltv[2].p = EE_RT(in); in.x -= s1; ltv[3].p = EE_RT(in); if(ltv[0].p.z > 0.f && ltv[1].p.z > 0.f && ltv[2].p.z > 0.f) { AddToShadowBatch(<v[0], <v[1], <v[2]); AddToShadowBatch(<v[0], <v[2], <v[3]); } } } else { for(size_t k = 0; k < io->obj->grouplist.size(); k++) { long origin = io->obj->grouplist[k].origin; EERIEPOLY *ep = CheckInPoly(io->obj->vertexlist3[origin].v); if(!ep) continue; Vec3f in; in.y = ep->min.y - 3.f; float r = 0.8f - ((float)glm::abs(io->obj->vertexlist3[origin].v.y - in.y)) * (1.f/500); r *= io->obj->grouplist[k].siz; r -= io->invisibility; if(r <= 0.f) continue; float s1 = io->obj->grouplist[k].siz * 44.f; float s2 = s1 * (1.f/2); in.x = io->obj->vertexlist3[origin].v.x - s2; in.z = io->obj->vertexlist3[origin].v.z - s2; r *= 255.f; long lv = r; ltv[0].color = ltv[1].color = ltv[2].color = ltv[3].color = Color(lv, lv, lv, 255).toRGBA(); ltv[0].p = EE_RT(in); in.x += s1; ltv[1].p = EE_RT(in); in.z += s1; ltv[2].p = EE_RT(in); in.x -= s1; ltv[3].p = EE_RT(in); AddToShadowBatch(<v[0], <v[1], <v[2]); AddToShadowBatch(<v[0], <v[2], <v[3]); } } } if(g_shadowBatch.size() > 0) { GRenderer->SetRenderState(Renderer::DepthWrite, false); GRenderer->SetBlendFunc(Renderer::BlendZero, Renderer::BlendInvSrcColor); GRenderer->SetRenderState(Renderer::AlphaBlending, true); GRenderer->SetTexture(0, Boom); EERIEDRAWPRIM(Renderer::TriangleList, &g_shadowBatch[0], g_shadowBatch.size()); GRenderer->SetRenderState(Renderer::AlphaBlending, false); GRenderer->SetRenderState(Renderer::DepthWrite, true); GRenderer->SetDepthBias(0); GRenderer->SetFogColor(ulBKGColor); } }
void TexturedSphere::build(int stacks, int slices, std::vector<TexturedVertex> *vertices, std::vector<unsigned int> *indices) { // Vertical step float phi_step = M_PI / stacks; // do not count the poles as rings int num_rings = stacks-1; // Compute vertices for each stack ring. for(unsigned int i = 1; i <= num_rings; ++i) { // Current vertical angle float phi = i*phi_step; // Vertices of ring float theta_step = 2.0f*M_PI / slices; for(unsigned int j = 0; j <= slices; ++j) { // Current horizontal angle float theta = j*theta_step; TexturedVertex v; // Convert from spherical to cartesian coords v.position[0] = glm::sin(phi) * glm::cos(theta); v.position[1] = glm::cos(phi); v.position[2] = glm::sin(phi) * glm::sin(theta); // Normal is equal to position for unit sphere v.normal = v.position; // Compute texture coords v.texcoord[0] = 1.0f - theta / (2.0f * M_PI); v.texcoord[1] = phi / M_PI; vertices->push_back(v); } } // Poles vertices->push_back(TexturedVertex(0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f)); vertices->push_back(TexturedVertex(0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f)); // Pole indices unsigned int north_pole_index = vertices->size()-1; unsigned int south_pole_index = vertices->size()-2; unsigned int num_ring_vertices = slices+1; // Compute indices for inner stacks (not connected to poles). for(unsigned int i = 0; i < stacks-2; ++i) { for(unsigned int j = 0; j < slices; ++j) { indices->push_back( i * num_ring_vertices + j); indices->push_back( i * num_ring_vertices + j+1); indices->push_back((i+1) * num_ring_vertices + j); indices->push_back((i+1) * num_ring_vertices + j); indices->push_back( i * num_ring_vertices + j+1); indices->push_back((i+1) * num_ring_vertices + j+1); } } // Compute indices for top stack for(unsigned int i = 0; i < slices; ++i) { indices->push_back(north_pole_index); indices->push_back(i+1); indices->push_back(i); } // Compute indices for bottom stack unsigned int base_index = (num_rings-1)*num_ring_vertices; for(unsigned int i = 0; i < slices; ++i) { indices->push_back(south_pole_index); indices->push_back(base_index+i); indices->push_back(base_index+i+1); } // Set the sizes m_vertex_count_ = vertices->size(); m_index_count_ = indices->size(); }
void StelQGLRenderer::drawRectInternal (const bool textured, const float x, const float y, const float width, const float height, const float angle) { statistics[RECT_DRAWS] += 1.0; // Could be improved by keeping the vertex buffer as a data member, // or even caching all rectangle draws to the same buffer and drawing them // at once at the end of the frame. Vec2f ne, nw, se, sw; // Faster path for angles that are zero or extremely small. if(abs(angle) < 0.1) { ne = Vec2f(x, y); nw = Vec2f(x + width, y); se = Vec2f(x, y + height); sw = Vec2f(x + width, y + height); } // Need to rotate the rectangle (around its center). else { const float cosr = std::cos(angle / 180 * M_PI); const float sinr = std::sin(angle / 180 * M_PI); const float halfWidth = width * 0.5; const float halfHeight = height * 0.5; const Vec2f center(x + halfWidth, y + halfHeight); const float widthCos = halfWidth * cosr; const float heightCos = halfHeight * cosr; const float widthSin = halfWidth * sinr; const float heightSin = halfHeight * sinr; ne = center + Vec2f(-widthCos + heightSin, -widthSin - heightCos); nw = center + Vec2f(widthCos + heightSin, widthSin - heightCos); se = center + Vec2f(-widthCos - heightSin, -widthSin + heightCos); sw = center + Vec2f(widthCos - heightSin, widthSin + heightCos); } // Prepare a vertex buffer for the rectangle and draw it. if(textured) { if(NULL == texturedRectBuffer) { texturedRectBuffer = createVertexBuffer<TexturedVertex>(PrimitiveType_TriangleStrip); } else { texturedRectBuffer->unlock(); texturedRectBuffer->clear(); } texturedRectBuffer->addVertex(TexturedVertex(ne, Vec2f(0.0f , 0.0f))); texturedRectBuffer->addVertex(TexturedVertex(nw, Vec2f(1.0f , 0.0f))); texturedRectBuffer->addVertex(TexturedVertex(se, Vec2f(0.0f , 1.0f))); texturedRectBuffer->addVertex(TexturedVertex(sw, Vec2f(1.0f , 1.0f))); texturedRectBuffer->lock(); drawVertexBuffer(texturedRectBuffer); } else { if(NULL == plainRectBuffer) { plainRectBuffer = createVertexBuffer<VertexP2>(PrimitiveType_TriangleStrip); } else { plainRectBuffer->unlock(); plainRectBuffer->clear(); } plainRectBuffer->addVertex(VertexP2(ne)); plainRectBuffer->addVertex(VertexP2(nw)); plainRectBuffer->addVertex(VertexP2(se)); plainRectBuffer->addVertex(VertexP2(sw)); plainRectBuffer->lock(); drawVertexBuffer(plainRectBuffer); } }
void StelQGLRenderer::drawText(const TextParams& params) { statistics[TEXT_DRAWS] += 1.0; StelQGLTextureBackend* currentTexture = currentlyBoundTextures[0]; if(params.string_.length() == 0) { return; } viewport.enablePainting(); if(currentFontSet) { viewport.setFont(currentFont); } QPainter* painter = viewport.getPainter(); Q_ASSERT_X(NULL != painter, Q_FUNC_INFO, "Trying to draw text but painting is disabled"); QFontMetrics fontMetrics = painter->fontMetrics(); StelProjectorP projector = NULL == params.projector_ ? StelApp::getInstance().getCore()->getProjection2d() : params.projector_; Vec3f win; if(params.doNotProject_) { win = params.position_; } else if(!projector->project(params.position_, win)) { viewport.disablePainting(); return; } const int x = win[0]; const int y = win[1]; // Avoid drawing if outside viewport. // We do a worst-case approximation as getting exact text dimensions is expensive. // We also account for rotation by assuming the worst case in bot X and Y // (culling with a rotating rectangle would be expensive) const int cullDistance = std::max(fontMetrics.height(), params.string_.size() * fontMetrics.maxWidth()); const Vec4i viewXywh = projector->getViewportXywh(); const int viewMinX = viewXywh[0]; const int viewMinY = viewXywh[1]; const int viewMaxX = viewMinX + viewXywh[2]; const int viewMaxY = viewMinY + viewXywh[3]; if(y + cullDistance < viewMinY || y - cullDistance > viewMaxY || x + cullDistance < viewMinX || x - cullDistance > viewMaxX) { viewport.disablePainting(); return; } if(projector->useGravityLabels() && !params.noGravity_) { drawTextGravityHelper(params, *painter, x, y, projector); return; } const int pixelSize = painter->font().pixelSize(); // Strings drawn by drawText() can differ by text, font size, or the font itself. const QByteArray hash = params.string_.toUtf8() + QByteArray::number(pixelSize) + painter->font().family().toUtf8(); StelQGLTextureBackend* textTexture = textTextureCache.object(hash); // No texture in cache for this string, need to draw it. if (NULL == textTexture) { const QRect extents = fontMetrics.boundingRect(params.string_); // Width and height of the text. // Texture width/height is required to be at least equal to this. // // Both X and Y need to be at least 1 so we don't create an empty image // (doesn't work with textures) const int requiredWidth = std::max(1, extents.width() + 1 + static_cast<int>(0.02f * extents.width())); const int requiredHeight = std::max(1, extents.height()); // Create temporary image and render text into it // QImage is used solely to reuse existing QGLTextureBackend constructor // function. QPixmap could be used as well (not sure which is faster, // needs profiling) QImage image = areNonPowerOfTwoTexturesSupported() ? QImage(requiredWidth, requiredHeight, QImage::Format_ARGB32_Premultiplied) : QImage(StelUtils::smallestPowerOfTwoGreaterOrEqualTo(requiredWidth), StelUtils::smallestPowerOfTwoGreaterOrEqualTo(requiredHeight), QImage::Format_ARGB32); image.fill(Qt::transparent); QPainter fontPainter(&image); fontPainter.setFont(painter->font()); fontPainter.setRenderHints(QPainter::TextAntialiasing, true); fontPainter.setPen(Qt::white); // The second argument ensures the text is positioned correctly even if // the image is enlarged to power-of-two. fontPainter.drawText(-extents.x(), image.height() - requiredHeight - extents.y(), params.string_); textTexture = StelQGLTextureBackend::constructFromImage (this, QString(), TextureParams().filtering(TextureFiltering_Linear), image); const QSize size = textTexture->getDimensions(); if(!textTexture->getStatus() == TextureStatus_Loaded) { qWarning() << "Texture error: " << textTexture->getErrorMessage(); Q_ASSERT_X(false, Q_FUNC_INFO, "Failed to construct a text texture"); } textTextureCache.insert(hash, textTexture, 4 * size.width() * size.height()); } // Even if NPOT textures are not supported, we always draw the full rectangle // of the texture. The extra space is fully transparent, so it's not an issue. // Shortcut variables to calculate the rectangle. const QSize size = textTexture->getDimensions(); const float w = size.width(); const float h = size.height(); const float xShift = params.xShift_; const float yShift = params.yShift_; const float angleDegrees = params.angleDegrees_ + (params.noGravity_ ? 0.0f : projector->getDefaultAngleForGravityText()); // Zero out very small angles. // // (this could also be used to optimize the case with zero angled // to avoid sin/cos if needed) const bool angled = std::fabs(angleDegrees) >= 1.0f * M_PI / 180.f; const float cosr = angled ? std::cos(angleDegrees * M_PI / 180.0) : 1.0f; const float sinr = angled ? std::sin(angleDegrees * M_PI / 180.0) : 0.0f; // Corners of the (possibly rotated) texture rectangle. const Vec2f ne(round(x + cosr * xShift - sinr * yShift), round(y + sinr * xShift + cosr * yShift)); const Vec2f nw(round(x + cosr * (w + xShift) - sinr * yShift), round(y + sinr * (w + xShift) + cosr * yShift)); const Vec2f se(round(x + cosr * xShift - sinr * (h + yShift)), round(y + sinr * xShift + cosr * (h + yShift))); const Vec2f sw(round(x + cosr * (w + xShift) - sinr * (h + yShift)), round(y + sinr * (w + xShift) + cosr * (h + yShift))); // Construct the text vertex buffer if it doesn't exist yet, otherwise clear it. if(NULL == textBuffer) { textBuffer = createVertexBuffer<TexturedVertex>(PrimitiveType_TriangleStrip); } else { textBuffer->unlock(); textBuffer->clear(); } textBuffer->addVertex(TexturedVertex(ne, Vec2f(0.0f, 0.0f))); textBuffer->addVertex(TexturedVertex(nw, Vec2f(1.0f, 0.0f))); textBuffer->addVertex(TexturedVertex(se, Vec2f(0.0f, 1.0f))); textBuffer->addVertex(TexturedVertex(sw, Vec2f(1.0f, 1.0f))); textBuffer->lock(); // Draw. const BlendMode oldBlendMode = blendMode; setBlendMode(BlendMode_Alpha); textTexture->bind(0); drawVertexBuffer(textBuffer); setBlendMode(oldBlendMode); // Reset user-bound texture. if(NULL != currentTexture) { currentTexture->bind(0); } viewport.disablePainting(); }
bool EERIECreateSprite(TexturedQuad& sprite, const Vec3f & in, float siz, Color color, float Zpos, float rot = 0) { TexturedVertex out; EE_RTP(in, &out); out.rhw *= 3000.f; if( out.p.z > 0.f && out.p.z < 1000.f && out.p.x > -1000.f && out.p.x < 2500.f && out.p.y > -500.f && out.p.y < 1800.f ) { float use_focal=BASICFOCAL*g_sizeRatio.x; float t; if(siz < 0) { t = -siz; } else { t = siz * ((out.rhw-1.f)*use_focal*0.001f); if(t <= 0.f) t = 0.00000001f; } if(Zpos <= 1.f) { out.p.z = Zpos; out.rhw = 1.f - out.p.z; } else { out.rhw *= (1.f/3000.f); } ColorRGBA col = color.toRGBA(); sprite.v[0] = TexturedVertex(Vec3f(), out.rhw, col, Vec2f_ZERO); sprite.v[1] = TexturedVertex(Vec3f(), out.rhw, col, Vec2f_X_AXIS); sprite.v[2] = TexturedVertex(Vec3f(), out.rhw, col, Vec2f(1.f, 1.f)); sprite.v[3] = TexturedVertex(Vec3f(), out.rhw, col, Vec2f_Y_AXIS); if(rot == 0) { Vec3f maxs = out.p + t; Vec3f mins = out.p - t; sprite.v[0].p = Vec3f(mins.x, mins.y, out.p.z); sprite.v[1].p = Vec3f(maxs.x, mins.y, out.p.z); sprite.v[2].p = Vec3f(maxs.x, maxs.y, out.p.z); sprite.v[3].p = Vec3f(mins.x, maxs.y, out.p.z); } else { for(long i=0;i<4;i++) { float tt = glm::radians(MAKEANGLE(rot+90.f*i+45+90)); sprite.v[i].p.x = std::sin(tt) * t + out.p.x; sprite.v[i].p.y = std::cos(tt) * t + out.p.y; sprite.v[i].p.z = out.p.z; } } return true; } return false; }
void ARXDRAW_DrawInterShadows() { GRenderer->SetFogColor(Color::none); SetZBias(1); long first=1; for(long i=0; i<TREATZONE_CUR; i++) { if(treatio[i].show != 1 || !treatio[i].io) continue; Entity *io = treatio[i].io; if(!io->obj || (io->ioflags & IO_JUST_COLLIDE)) continue; FAST_BKG_DATA * bkgData = getFastBackgroundData(io->pos.x, io->pos.z); if(bkgData && !bkgData->treat) { //TODO is that correct ? continue; } if(!(io->ioflags & IO_NOSHADOW) && io->show==SHOW_FLAG_IN_SCENE && !(io->ioflags & IO_GOLD)) { TexturedVertex in; TexturedVertex ltv[4]; ltv[0] = TexturedVertex(Vec3f(0, 0, 0.001f), 1.f, 0, 1, Vec2f(0.3f, 0.3f)); ltv[1] = TexturedVertex(Vec3f(0, 0, 0.001f), 1.f, 0, 1, Vec2f(0.7f, 0.3f)); ltv[2] = TexturedVertex(Vec3f(0, 0, 0.001f), 1.f, 0, 1, Vec2f(0.7f, 0.7f)); ltv[3] = TexturedVertex(Vec3f(0, 0, 0.001f), 1.f, 0, 1, Vec2f(0.3f, 0.7f)); if(io->obj->nbgroups <= 1) { for(size_t k=0; k < io->obj->vertexlist.size(); k += 9) { EERIEPOLY *ep = EECheckInPoly(&io->obj->vertexlist3[k].v); if(ep) { in.p.y=ep->min.y-3.f; float r=0.5f-((float)EEfabs(io->obj->vertexlist3[k].v.y-in.p.y))*( 1.0f / 500 ); r-=io->invisibility; r*=io->scale; if(r<=0.f) continue; float s1=16.f*io->scale; float s2=s1*( 1.0f / 2 ); in.p.x=io->obj->vertexlist3[k].v.x-s2; in.p.z=io->obj->vertexlist3[k].v.z-s2; r*=255.f; long lv = r; ltv[0].color=ltv[1].color=ltv[2].color=ltv[3].color=0xFF000000 | lv<<16 | lv<<8 | lv; if(first) { first=0; GRenderer->SetRenderState(Renderer::DepthWrite, false); GRenderer->SetBlendFunc(Renderer::BlendZero, Renderer::BlendInvSrcColor); GRenderer->SetRenderState(Renderer::AlphaBlending, true); GRenderer->SetTexture(0, Boom); } EE_RT2(&in,<v[0]); in.p.x+=s1; EE_RT2(&in,<v[1]); in.p.z+=s1; EE_RT2(&in,<v[2]); in.p.x-=s1; EE_RT2(&in,<v[3]); if(ltv[0].p.z > 0.f && ltv[1].p.z > 0.f && ltv[2].p.z > 0.f) { ARX_DrawPrimitive(<v[0], <v[1], <v[2], 50.0f); ARX_DrawPrimitive(<v[0], <v[2], <v[3], 50.0f); } } } } else { for(long k = 0; k < io->obj->nbgroups; k++) { long origin=io->obj->grouplist[k].origin; EERIEPOLY *ep = EECheckInPoly(&io->obj->vertexlist3[origin].v); if(ep) { in.p.y=ep->min.y-3.f; float r=0.8f-((float)EEfabs(io->obj->vertexlist3[origin].v.y-in.p.y))*( 1.0f / 500 ); r*=io->obj->grouplist[k].siz; r-=io->invisibility; if(r<=0.f) continue; float s1=io->obj->grouplist[k].siz*44.f; float s2=s1*( 1.0f / 2 ); in.p.x=io->obj->vertexlist3[origin].v.x-s2; in.p.z=io->obj->vertexlist3[origin].v.z-s2; r*=255.f; long lv = r; ltv[0].color=ltv[1].color=ltv[2].color=ltv[3].color=0xFF000000 | lv<<16 | lv<<8 | lv; if(first) { first=0; GRenderer->SetRenderState(Renderer::DepthWrite, false); GRenderer->SetBlendFunc(Renderer::BlendZero, Renderer::BlendInvSrcColor); GRenderer->SetRenderState(Renderer::AlphaBlending, true); GRenderer->SetTexture(0, Boom); } EE_RT2(&in,<v[0]); in.p.x+=s1; EE_RT2(&in,<v[1]); in.p.z+=s1; EE_RT2(&in,<v[2]); in.p.x-=s1; EE_RT2(&in,<v[3]); ARX_DrawPrimitive(<v[0], <v[1], <v[2]); ARX_DrawPrimitive(<v[0], <v[2], <v[3]); } } } } } GRenderer->SetRenderState(Renderer::AlphaBlending, false); GRenderer->SetRenderState(Renderer::DepthWrite, true); SetZBias(0); GRenderer->SetFogColor(ulBKGColor); }