void drawTransparentFogObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix) { GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; const Track * const track = World::getWorld()->getTrack(); // This function is only called once per frame - thus no need for setters. const float fogmax = track->getFogMax(); const float startH = track->getFogStartHeight(); const float endH = track->getFogEndHeight(); const float start = track->getFogStart(); const float end = track->getFogEnd(); const video::SColor tmpcol = track->getFogColor(); core::vector3df col(tmpcol.getRed() / 255.0f, tmpcol.getGreen() / 255.0f, tmpcol.getBlue() / 255.0f); setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); glUseProgram(MeshShader::TransparentFogShader::Program); MeshShader::TransparentFogShader::setUniforms(ModelViewProjectionMatrix, TextureMatrix, irr_driver->getInvProjMatrix(), fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0); glBindVertexArray(mesh.vao_first_pass); glDrawElements(ptype, count, itype, 0); }
/* Converts from day + night color values (0..255) and a given daynight_ratio to the final SColor shown on screen. */ void finalColorBlend(video::SColor& result, u8 day, u8 night, u32 daynight_ratio) { s32 rg = (day * daynight_ratio + night * (1000-daynight_ratio)) / 1000; s32 b = rg; // Moonlight is blue b += (day - night) / 13; rg -= (day - night) / 23; // Emphase blue a bit in darker places // Each entry of this array represents a range of 8 blue levels static const u8 emphase_blue_when_dark[35] = { 1, 4, 6, 6, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; b += emphase_blue_when_dark[b / 8]; b = irr::core::clamp (b, 0, 255); // Artificial light is yellow-ish static const u8 emphase_yellow_when_artificial[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 10, 15, 15, 15 }; rg += emphase_yellow_when_artificial[night/16]; rg = irr::core::clamp (rg, 0, 255); result.setRed(rg); result.setGreen(rg); result.setBlue(b); }
//! Default constructor for color list CNumbersAttribute::CNumbersAttribute(const c8* name, video::SColor value) : ValueI(), ValueF(), Count(4), IsFloat(false) { Name = name; ValueI.pushBack(value.getRed()); ValueI.pushBack(value.getGreen()); ValueI.pushBack(value.getBlue()); ValueI.pushBack(value.getAlpha()); }
void COBJMeshWriter::getColorAsStringLine(const video::SColor& color, const c8* const prefix, core::stringc& s) const { s = prefix; s += " "; s += core::stringc(color.getRed()/255.f); s += " "; s += core::stringc(color.getGreen()/255.f); s += " "; s += core::stringc(color.getBlue()/255.f); s += "\n"; }
void push_ARGB8(lua_State *L, video::SColor color) { lua_newtable(L); lua_pushnumber(L, color.getAlpha()); lua_setfield(L, -2, "a"); lua_pushnumber(L, color.getRed()); lua_setfield(L, -2, "r"); lua_pushnumber(L, color.getGreen()); lua_setfield(L, -2, "g"); lua_pushnumber(L, color.getBlue()); lua_setfield(L, -2, "b"); }
void CNumbersAttribute::setColor(video::SColor color) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = (f32) color.getRed() / 255.0f; if (Count > 1) ValueF[1] = (f32) color.getGreen() / 255.0f; if (Count > 2) ValueF[2] = (f32) color.getBlue() / 255.0f; if (Count > 3) ValueF[3] = (f32) color.getAlpha() / 255.0f; } else { if (Count > 0) ValueI[0] = color.getRed(); if (Count > 1) ValueI[1] = color.getGreen(); if (Count > 2) ValueI[2] = color.getBlue(); if (Count > 3) ValueI[3] = color.getAlpha(); } }
// Fill the editfields with the value for the given color void CColorControl::setEditsFromColor(video::SColor col) { DirtyFlag = true; if ( EditAlpha ) EditAlpha->setText( core::stringw(col.getAlpha()).c_str() ); if ( EditRed ) EditRed->setText( core::stringw(col.getRed()).c_str() ); if ( EditGreen ) EditGreen->setText( core::stringw(col.getGreen()).c_str() ); if ( EditBlue ) EditBlue->setText( core::stringw(col.getBlue()).c_str() ); if ( ColorStatic ) ColorStatic->setBackgroundColor(col); }
void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position, const core::rect<s32>* clip) { if (!irr_driver->isGLSL()) { irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip); return; } core::dimension2d<u32> frame_size = irr_driver->getVideoDriver()->getCurrentRenderTargetSize(); const int screen_w = frame_size.Width; const int screen_h = frame_size.Height; float center_pos_x = float(position.UpperLeftCorner.X + position.LowerRightCorner.X); center_pos_x /= screen_w; center_pos_x -= 1; float center_pos_y = float(position.UpperLeftCorner.Y + position.LowerRightCorner.Y); center_pos_y /= screen_h; center_pos_y = 1 - center_pos_y; float width = float(position.LowerRightCorner.X - position.UpperLeftCorner.X); width /= screen_w; float height = float(position.LowerRightCorner.Y - position.UpperLeftCorner.Y); height /= screen_h; if (color.getAlpha() < 255) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else { glDisable(GL_BLEND); } if (clip) { if (!clip->isValid()) return; glEnable(GL_SCISSOR_TEST); const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize(); glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y, clip->getWidth(), clip->getHeight()); } glUseProgram(UIShader::ColoredRectShader::getInstance()->Program); glBindVertexArray(SharedObject::UIVAO); UIShader::ColoredRectShader::getInstance()->setUniforms(core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), color); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); if (clip) glDisable(GL_SCISSOR_TEST); glUseProgram(0); glGetError(); }
void IrrDriver::renderLightsScatter(unsigned pointlightcount) { getFBO(FBO_HALF1).Bind(); glClearColor(0., 0., 0., 0.); glClear(GL_COLOR_BUFFER_BIT); const Track * const track = World::getWorld()->getTrack(); // This function is only called once per frame - thus no need for setters. float start = track->getFogStart() + .001; const video::SColor tmpcol = track->getFogColor(); core::vector3df col(tmpcol.getRed() / 255.0f, tmpcol.getGreen() / 255.0f, tmpcol.getBlue() / 255.0f); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ONE, GL_ONE); FullScreenShader::FogShader::getInstance()->SetTextureUnits(irr_driver->getDepthStencilTexture()); DrawFullScreenEffect<FullScreenShader::FogShader>(1.f / (40.f * start), col); glEnable(GL_DEPTH_TEST); core::vector3df col2(1., 1., 1.); glUseProgram(LightShader::PointLightScatterShader::getInstance()->Program); glBindVertexArray(LightShader::PointLightScatterShader::getInstance()->vao); LightShader::PointLightScatterShader::getInstance()->SetTextureUnits(irr_driver->getDepthStencilTexture()); LightShader::PointLightScatterShader::getInstance()->setUniforms(1.f / (40.f * start), col2); glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, MIN2(pointlightcount, MAXLIGHT)); glDisable(GL_BLEND); m_post_processing->renderGaussian6Blur(getFBO(FBO_HALF1), getFBO(FBO_HALF2), 5., 5.); glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); getFBO(FBO_COLORS).Bind(); m_post_processing->renderPassThrough(getRenderTargetTexture(RTT_HALF1)); }
/** Compute spherical harmonics coefficients from ambient light */ void SphericalHarmonics::setAmbientLight(const video::SColor &ambient) { //do not recompute SH coefficients if we already use the same ambient light if((m_spherical_harmonics_textures.size() != 6) && (ambient == m_ambient)) return; m_spherical_harmonics_textures.clear(); m_ambient = ambient; unsigned char *sh_rgba[6]; unsigned sh_w = 16; unsigned sh_h = 16; for (unsigned i = 0; i < 6; i++) { sh_rgba[i] = new unsigned char[sh_w * sh_h * 4]; for (unsigned j = 0; j < sh_w * sh_h * 4; j += 4) { sh_rgba[i][j] = ambient.getBlue(); sh_rgba[i][j + 1] = ambient.getGreen(); sh_rgba[i][j + 2] = ambient.getRed(); sh_rgba[i][j + 3] = 255; } } Color *float_tex_cube[6]; convertToFloatTexture(sh_rgba, sh_w, sh_h, float_tex_cube); generateSphericalHarmonics(float_tex_cube, sh_w); for (unsigned i = 0; i < 6; i++) { delete[] sh_rgba[i]; delete[] float_tex_cube[i]; } // Diffuse env map is x 0.25, compensate for (unsigned i = 0; i < 9; i++) { m_blue_SH_coeff[i] *= 4; m_green_SH_coeff[i] *= 4; m_red_SH_coeff[i] *= 4; } } //setAmbientLight
void WieldMeshSceneNode::setColor(video::SColor c) { assert(!m_lighting); scene::IMesh *mesh = m_meshnode->getMesh(); if (!mesh) return; u8 red = c.getRed(); u8 green = c.getGreen(); u8 blue = c.getBlue(); u32 mc = mesh->getMeshBufferCount(); for (u32 j = 0; j < mc; j++) { video::SColor bc(m_base_color); if ((m_colors.size() > j) && (m_colors[j].override_base)) bc = m_colors[j].color; video::SColor buffercolor(255, bc.getRed() * red / 255, bc.getGreen() * green / 255, bc.getBlue() * blue / 255); scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); colorizeMeshBuffer(buf, &buffercolor); } }
void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position, const core::rect<s32>* clip) { if (!irr_driver->isGLSL()) { irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip); return; } core::dimension2d<u32> frame_size = irr_driver->getVideoDriver()->getCurrentRenderTargetSize(); const int screen_w = frame_size.Width; const int screen_h = frame_size.Height; float center_pos_x = position.UpperLeftCorner.X + position.LowerRightCorner.X; center_pos_x /= screen_w; center_pos_x -= 1; float center_pos_y = position.UpperLeftCorner.Y + position.LowerRightCorner.Y; center_pos_y /= screen_h; center_pos_y = 1 - center_pos_y; float width = position.LowerRightCorner.X - position.UpperLeftCorner.X; width /= screen_w; float height = position.LowerRightCorner.Y - position.UpperLeftCorner.Y; height /= screen_h; if (color.getAlpha() < 255) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else { glDisable(GL_BLEND); } glUseProgram(UIShader::ColoredRectShader::Program); glBindVertexArray(UIShader::ColoredRectShader::vao); UIShader::ColoredRectShader::setUniforms(center_pos_x, center_pos_y, width, height, color); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); glUseProgram(0); }
bool drawLine( video::IImage* dst, s32 x0, s32 y0, s32 x1, s32 y1, const video::SColor& color_a, const video::SColor& color_b, bool blend ) { if (!dst) return false; const core::dimension2du img_size = dst->getDimension(); if ((img_size.Width == 0) || (img_size.Height == 0)) return false; const s32 dx = core::abs_<s32>( x1 - x0 ); const s32 dy = core::abs_<s32>( y1 - y0 ); if ((dx==0) && (dy==0)) return false; s32 sx = 1; // sign s32 sy = 1; // sign if (x0 > x1) sx = -1; if (y0 > y1) sy = -1; s32 err = dx-dy; s32 e2 = 0; s32 x = x0; s32 y = y0; s32 numpixels = 0; // count pixels while (1) { numpixels++; if ((x==x1) && (y==y1)) break; e2 = err << 1; if (e2 > -dy) { err -= dy; x += sx; } if (e2 < dx) { err += dx; y += sy; } } // reset vars; err = dx-dy; e2 = 0; x = x0; y = y0; // values for linear color interpolation const f32 A1=(f32)color_a.getAlpha(); const f32 R1=(f32)color_a.getRed(); const f32 G1=(f32)color_a.getGreen(); const f32 B1=(f32)color_a.getBlue(); const f32 dA=(f32)color_b.getAlpha()-A1; const f32 dR=(f32)color_b.getRed()-R1; const f32 dG=(f32)color_b.getGreen()-G1; const f32 dB=(f32)color_b.getBlue()-B1; // actual drawing f32 f=0.f; s32 k=0; u32 cR=0, cG=0, cB=0, cA=0; while (1) { f = (f32)k/(f32)numpixels; k++; cA=A1; cR=R1; cG=G1; cB=B1; // maybe faster under the assumption that colors have most likely same alpha value if (dA>0) cA = (u32)core::clamp( core::round32(A1+dA*f), 0, 255); if (dR>0) cR = (u32)core::clamp( core::round32(R1+dR*f), 0, 255); if (dG>0) cG = (u32)core::clamp( core::round32(G1+dG*f), 0, 255); if (dB>0) cB = (u32)core::clamp( core::round32(B1+dB*f), 0, 255); drawPixel( dst, x, y, video::SColor( cA, cR, cG, cB), blend ); if (x == x1 && y == y1) break; e2 = err << 1; if (e2 > -dy) { err -= dy; x += sx; } if (e2 < dx) { err += dx; y += sy; } } return true; }
// ---------------------------------------------------------------------------- void FontWithFace::render(const core::stringw& text, const core::rect<s32>& position, const video::SColor& color, bool hcenter, bool vcenter, const core::rect<s32>* clip, FontSettings* font_settings, FontCharCollector* char_collector) { const bool is_bold_face = dynamic_cast<BoldFace*>(this); const bool black_border = font_settings ? font_settings->useBlackBorder() : false; const bool rtl = font_settings ? font_settings->isRTL() : false; const float scale = font_settings ? font_settings->getScale() : 1.0f; const float shadow = font_settings ? font_settings->useShadow() : false; if (shadow) { assert(font_settings); // Avoid infinite recursion font_settings->setShadow(false); core::rect<s32> shadowpos = position; shadowpos.LowerRightCorner.X += 2; shadowpos.LowerRightCorner.Y += 2; render(text, shadowpos, font_settings->getShadowColor(), hcenter, vcenter, clip, font_settings); // Set back font_settings->setShadow(true); } core::position2d<float> offset(float(position.UpperLeftCorner.X), float(position.UpperLeftCorner.Y)); core::dimension2d<s32> text_dimension; if (rtl || hcenter || vcenter || clip) { text_dimension = getDimension(text.c_str(), font_settings); if (hcenter) offset.X += (position.getWidth() - text_dimension.Width) / 2; else if (rtl) offset.X += (position.getWidth() - text_dimension.Width); if (vcenter) offset.Y += (position.getHeight() - text_dimension.Height) / 2; if (clip) { core::rect<s32> clippedRect(core::position2d<s32> (s32(offset.X), s32(offset.Y)), text_dimension); clippedRect.clipAgainst(*clip); if (!clippedRect.isValid()) return; } } // Collect character locations const unsigned int text_size = text.size(); core::array<s32> indices(text_size); core::array<core::position2d<float>> offsets(text_size); std::vector<bool> fallback(text_size); // Test again if lazy load char is needed, // as some text isn't drawn with getDimension insertCharacters(text.c_str()); updateCharactersList(); for (u32 i = 0; i < text_size; i++) { wchar_t c = text[i]; if (c == L'\r' || // Windows breaks c == L'\n' ) // Unix breaks { if (c==L'\r' && text[i+1]==L'\n') c = text[++i]; offset.Y += m_font_max_height * scale; offset.X = position.UpperLeftCorner.X; if (hcenter) offset.X += (position.getWidth() - text_dimension.Width) >> 1; continue; } // if lineBreak bool use_fallback_font = false; const FontArea &area = getAreaFromCharacter(c, &use_fallback_font); fallback[i] = use_fallback_font; if (char_collector == NULL) { float glyph_offset_x = area.bearing_x * (fallback[i] ? m_fallback_font_scale : scale); float glyph_offset_y = area.offset_y * (fallback[i] ? m_fallback_font_scale : scale); offset.X += glyph_offset_x; offset.Y += glyph_offset_y; offsets.push_back(offset); offset.X -= glyph_offset_x; offset.Y -= glyph_offset_y; } else { // Prevent overwriting texture used by billboard text when // using lazy loading characters if (supportLazyLoadChar() && fallback[i]) { const int cur_texno = m_fallback_font->getSpriteBank() ->getSprites()[area.spriteno].Frames[0].textureNumber; if (cur_texno == int(m_fallback_font->getSpriteBank() ->getTextureCount() - 1)) { m_fallback_font->createNewGlyphPage(); } } else if (supportLazyLoadChar()) { const int cur_texno = m_spritebank ->getSprites()[area.spriteno].Frames[0].textureNumber; if (cur_texno == int(m_spritebank->getTextureCount() - 1)) { createNewGlyphPage(); } } // Billboard text specific, use offset_y_bt instead float glyph_offset_x = area.bearing_x * (fallback[i] ? m_fallback_font_scale : scale); float glyph_offset_y = area.offset_y_bt * (fallback[i] ? m_fallback_font_scale : scale); offset.X += glyph_offset_x; offset.Y += glyph_offset_y; offsets.push_back(offset); offset.X -= glyph_offset_x; offset.Y -= glyph_offset_y; } indices.push_back(area.spriteno); offset.X += getCharWidth(area, fallback[i], scale); } // for i < text_size // Do the actual rendering const int indice_amount = indices.size(); core::array<gui::SGUISprite>& sprites = m_spritebank->getSprites(); core::array<core::rect<s32>>& positions = m_spritebank->getPositions(); core::array<gui::SGUISprite>* fallback_sprites; core::array<core::rect<s32>>* fallback_positions; if (m_fallback_font != NULL) { fallback_sprites = &m_fallback_font->m_spritebank->getSprites(); fallback_positions = &m_fallback_font->m_spritebank->getPositions(); } else { fallback_sprites = NULL; fallback_positions = NULL; } const int sprite_amount = sprites.size(); if ((black_border || is_bold_face) && char_collector == NULL) { // Draw black border first, to make it behind the real character // which make script language display better video::SColor black(color.getAlpha(),0,0,0); for (int n = 0; n < indice_amount; n++) { const int sprite_id = indices[n]; if (!fallback[n] && (sprite_id < 0 || sprite_id >= sprite_amount)) continue; if (indices[n] == -1) continue; const int tex_id = (fallback[n] ? (*fallback_sprites)[sprite_id].Frames[0].textureNumber : sprites[sprite_id].Frames[0].textureNumber); core::rect<s32> source = (fallback[n] ? (*fallback_positions) [(*fallback_sprites)[sprite_id].Frames[0].rectNumber] : positions[sprites[sprite_id].Frames[0].rectNumber]); core::dimension2d<float> size(0.0f, 0.0f); float cur_scale = (fallback[n] ? m_fallback_font_scale : scale); size.Width = source.getSize().Width * cur_scale; size.Height = source.getSize().Height * cur_scale; core::rect<float> dest(offsets[n], size); video::ITexture* texture = (fallback[n] ? m_fallback_font->m_spritebank->getTexture(tex_id) : m_spritebank->getTexture(tex_id)); for (int x_delta = -2; x_delta <= 2; x_delta++) { for (int y_delta = -2; y_delta <= 2; y_delta++) { if (x_delta == 0 || y_delta == 0) continue; draw2DImage(texture, dest + core::position2d<float> (float(x_delta), float(y_delta)), source, clip, black, true); } } } } for (int n = 0; n < indice_amount; n++) { const int sprite_id = indices[n]; if (!fallback[n] && (sprite_id < 0 || sprite_id >= sprite_amount)) continue; if (indices[n] == -1) continue; const int tex_id = (fallback[n] ? (*fallback_sprites)[sprite_id].Frames[0].textureNumber : sprites[sprite_id].Frames[0].textureNumber); core::rect<s32> source = (fallback[n] ? (*fallback_positions)[(*fallback_sprites)[sprite_id].Frames[0] .rectNumber] : positions[sprites[sprite_id].Frames[0].rectNumber]); core::dimension2d<float> size(0.0f, 0.0f); float cur_scale = (fallback[n] ? m_fallback_font_scale : scale); size.Width = source.getSize().Width * cur_scale; size.Height = source.getSize().Height * cur_scale; core::rect<float> dest(offsets[n], size); video::ITexture* texture = (fallback[n] ? m_fallback_font->m_spritebank->getTexture(tex_id) : m_spritebank->getTexture(tex_id)); if (fallback[n] || is_bold_face) { video::SColor top = GUIEngine::getSkin()->getColor("font::top"); video::SColor bottom = GUIEngine::getSkin() ->getColor("font::bottom"); top.setAlpha(color.getAlpha()); bottom.setAlpha(color.getAlpha()); video::SColor title_colors[] = {top, bottom, top, bottom}; if (char_collector != NULL) { char_collector->collectChar(texture, dest, source, title_colors); } else { draw2DImage(texture, dest, source, clip, title_colors, true); } } else { if (char_collector != NULL) { video::SColor colors[] = {color, color, color, color}; char_collector->collectChar(texture, dest, source, colors); } else { draw2DImage(texture, dest, source, clip, color, true); } } } } // render
void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position, const core::rect<s32>* clip) { if (!irr_driver->isGLSL()) { irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip); return; } core::dimension2d<u32> frame_size = irr_driver->getVideoDriver()->getCurrentRenderTargetSize(); const int screen_w = frame_size.Width; const int screen_h = frame_size.Height; float center_pos_x = position.UpperLeftCorner.X + position.LowerRightCorner.X; center_pos_x /= screen_w; center_pos_x -= 1; float center_pos_y = position.UpperLeftCorner.Y + position.LowerRightCorner.Y; center_pos_y /= screen_h; center_pos_y = 1 - center_pos_y; float width = position.LowerRightCorner.X - position.UpperLeftCorner.X; width /= screen_w; float height = position.LowerRightCorner.Y - position.UpperLeftCorner.Y; height /= screen_h; if (color.getAlpha() < 255) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else { glDisable(GL_BLEND); } if (clip) { if (!clip->isValid()) return; glEnable(GL_SCISSOR_TEST); const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize(); glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y, clip->getWidth(), clip->getHeight()); } glUseProgram(UIShader::ColoredRectShader::Program); glBindVertexArray(UIShader::ColoredRectShader::vao); UIShader::ColoredRectShader::setUniforms(center_pos_x, center_pos_y, width, height, color); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); if (clip) glDisable(GL_SCISSOR_TEST); glUseProgram(0); GLenum glErr = glGetError(); if (glErr != GL_NO_ERROR) { Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr); } }
aiColor3D IrrToAssimpColor(video::SColor color) { return aiColor3D(color.getRed() / 255.f, color.getGreen() / 255.f, color.getBlue() / 255.f); }
void ScalableFont::doDraw(const core::stringw& text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip, FontCharCollector* charCollector) { if (!m_video_driver) return; GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator(); if (m_shadow) { m_shadow = false; // avoid infinite recursion core::rect<s32> shadowpos = position; shadowpos.LowerRightCorner.X += 2; shadowpos.LowerRightCorner.Y += 2; draw(text, shadowpos, m_shadow_color, hcenter, vcenter, clip); m_shadow = true; // set back } core::position2d<s32> offset = position.UpperLeftCorner; core::dimension2d<s32> text_dimension; if (m_rtl || hcenter || vcenter || clip) { text_dimension = getDimension(text.c_str()); if (hcenter) offset.X += (position.getWidth() - text_dimension.Width) / 2; else if (m_rtl) offset.X += (position.getWidth() - text_dimension.Width); if (vcenter) offset.Y += (position.getHeight() - text_dimension.Height) / 2; if (clip) { core::rect<s32> clippedRect(offset, text_dimension); clippedRect.clipAgainst(*clip); if (!clippedRect.isValid()) return; } } // ---- collect character locations const unsigned int text_size = text.size(); core::array<s32> indices(text_size); core::array<core::position2di> offsets(text_size); std::vector<bool> fallback(text_size); if (m_type == T_NORMAL || T_BOLD) //lazy load char, have to do this again { //because some text isn't drawn with getDimension for (u32 i = 0; i < text_size; i++) { wchar_t c = text[i]; if (c == L'\r' || c == L'\n' || c == L' ' || c < 32) continue; if (!GUIEngine::getFont()->hasThisChar(c)) gp_creator->insertChar(c); if (charCollector != NULL && m_type == T_NORMAL && m_spritebank->getSprites() [GUIEngine::getFont()->getSpriteNoFromChar(&c)].Frames[0].textureNumber == m_spritebank->getTextureCount() - 1) //Prevent overwriting texture used by billboard text { Log::debug("ScalableFont::doDraw", "Character used by billboard text is in the last " "glyph page of normal font. Create a new glyph " "page for new characters inserted later to prevent " "it from being removed."); GUIEngine::getFont()->forceNewPage(); } } if (gp_creator->getNewChar().size() > 0 && !m_is_hollow_copy && m_scale == 1) { Log::debug("ScalableFont::doDraw", "New character(s) %s discoverd, perform lazy loading", StringUtils::wideToUtf8(gp_creator->getNewChar()).c_str()); if (!GUIEngine::getFont()->lazyLoadChar()) Log::error("ScalableFont::lazyLoadChar", "Can't insert new char into glyph pages."); } } for (u32 i = 0; i < text_size; i++) { wchar_t c = text[i]; if (c == L'\r' || // Windows breaks c == L'\n' ) // Unix breaks { if(c==L'\r' && text[i+1]==L'\n') c = text[++i]; offset.Y += (int)(m_max_height*m_scale); offset.X = position.UpperLeftCorner.X; if (hcenter) offset.X += (position.getWidth() - text_dimension.Width) >> 1; continue; } // if lineBreak bool use_fallback_font = false; const SFontArea &area = getAreaFromCharacter(c, &use_fallback_font); fallback[i] = use_fallback_font; if (charCollector == NULL) { //Try to use ceil to make offset calculate correctly when m_scale is smaller than 1 s32 glyph_offset_x = (s32)((float) area.bearingx* (fallback[i] ? m_scale*m_fallback_font_scale : m_scale)); s32 glyph_offset_y = (s32)ceil((float) area.offsety* (fallback[i] ? m_scale*m_fallback_font_scale : m_scale)); offset.X += glyph_offset_x; offset.Y += s32(glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0)); //Additional offset for digit text offsets.push_back(offset); offset.X -= glyph_offset_x; offset.Y -= s32(glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0)); } else //Billboard text specific { s32 glyph_offset_x = (s32)ceil((float) area.bearingx* (fallback[i] ? m_scale*m_fallback_font_scale : m_scale)); s32 glyph_offset_y = (s32)ceil((float) area.offsety_bt* (fallback[i] ? m_scale*m_fallback_font_scale : m_scale)); offset.X += glyph_offset_x; offset.Y += s32(glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0)); //Additional offset for digit text offsets.push_back(offset); offset.X -= glyph_offset_x; offset.Y -= s32(glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0)); } // Invisible character. add something to the array anyway so that // indices from the various arrays remain in sync indices.push_back(m_invisible.findFirst(c) < 0 ? area.spriteno : -1); offset.X += getCharWidth(area, fallback[i]); } // for i<text_size // ---- do the actual rendering const int indiceAmount = indices.size(); core::array< SGUISprite >& sprites = m_spritebank->getSprites(); core::array< core::rect<s32> >& positions = m_spritebank->getPositions(); core::array< SGUISprite >* fallback_sprites; core::array< core::rect<s32> >* fallback_positions; if (m_fallback_font != NULL) { fallback_sprites = &m_fallback_font->m_spritebank->getSprites(); fallback_positions = &m_fallback_font->m_spritebank->getPositions(); } else { fallback_sprites = NULL; fallback_positions = NULL; } const int spriteAmount = sprites.size(); if (m_black_border && charCollector == NULL) { //Draw black border first, to make it behind the real character //which make script language display better video::SColor black(color.getAlpha(),0,0,0); for (int n = 0; n < indiceAmount; n++) { const int spriteID = indices[n]; if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue; if (indices[n] == -1) continue; const int texID = (fallback[n] ? (*fallback_sprites)[spriteID].Frames[0].textureNumber : sprites[spriteID].Frames[0].textureNumber); core::rect<s32> source = (fallback[n] ? (*fallback_positions)[(*fallback_sprites)[spriteID].Frames[0].rectNumber] : positions[sprites[spriteID].Frames[0].rectNumber]); core::dimension2d<s32> size = source.getSize(); float scale = (fallback[n] ? m_scale*m_fallback_font_scale : m_scale); size.Width = (int)(size.Width * scale); size.Height = (int)(size.Height * scale); core::rect<s32> dest(offsets[n], size); video::ITexture* texture = (fallback[n] ? m_fallback_font->m_spritebank->getTexture(texID) : m_spritebank->getTexture(texID) ); for (int x_delta = -2; x_delta <= 2; x_delta++) { for (int y_delta = -2; y_delta <= 2; y_delta++) { if (x_delta == 0 || y_delta == 0) continue; draw2DImage(texture, dest + core::position2d<s32>(x_delta, y_delta), source, clip, black, true); } } } } for (int n = 0; n < indiceAmount; n++) { const int spriteID = indices[n]; if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue; if (indices[n] == -1) continue; //assert(sprites[spriteID].Frames.size() > 0); const int texID = (fallback[n] ? (*fallback_sprites)[spriteID].Frames[0].textureNumber : sprites[spriteID].Frames[0].textureNumber); core::rect<s32> source = (fallback[n] ? (*fallback_positions)[(*fallback_sprites)[spriteID].Frames[0].rectNumber] : positions[sprites[spriteID].Frames[0].rectNumber]); core::dimension2d<s32> size = source.getSize(); float scale = (fallback[n] ? m_scale*m_fallback_font_scale : m_scale); size.Width = (int)(size.Width * scale); size.Height = (int)(size.Height * scale); core::rect<s32> dest(offsets[n], size); video::ITexture* texture = (fallback[n] ? m_fallback_font->m_spritebank->getTexture(texID) : m_spritebank->getTexture(texID) ); /* if (fallback[n]) { Log::info("ScalableFont", "Using fallback font %s; source area is %d, %d; size %d, %d; dest = %d, %d", core::stringc(texture->getName()).c_str(), source.UpperLeftCorner.X, source.UpperLeftCorner.Y, source.getWidth(), source.getHeight(), offsets[n].X, offsets[n].Y); } */ #ifdef FONT_DEBUG GL32_draw2DRectangle(video::SColor(255, 255,0,0), dest,clip); #endif if (fallback[n] || m_type == T_BOLD) { video::SColor top = GUIEngine::getSkin()->getColor("font::top"); video::SColor bottom = GUIEngine::getSkin()->getColor("font::bottom"); top.setAlpha(color.getAlpha()); bottom.setAlpha(color.getAlpha()); video::SColor title_colors[] = {top, bottom, top, bottom}; if (charCollector != NULL) { charCollector->collectChar(texture, dest, source, title_colors); } else { draw2DImage(texture, dest, source, clip, title_colors, true); } } else { if (charCollector != NULL) { video::SColor colors[] = { color, color, color, color }; charCollector->collectChar(texture, dest, source, colors); } else { draw2DImage(texture, dest, source, clip, color, true); } } } }
//! draws some text and clips it to the specified rectangle if wanted void ScalableFont::doDraw(const core::stringw& text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip, FontCharCollector* charCollector) { if (!Driver) return; if (m_shadow) { m_shadow = false; // avoid infinite recursion core::rect<s32> shadowpos = position; shadowpos.LowerRightCorner.X += 2; shadowpos.LowerRightCorner.Y += 2; draw(text, shadowpos, m_shadow_color, hcenter, vcenter, clip); m_shadow = true; // set back } core::position2d<s32> offset = position.UpperLeftCorner; core::dimension2d<s32> text_dimension; if (m_rtl || hcenter || vcenter || clip) { text_dimension = getDimension(text.c_str()); if (hcenter) offset.X += (position.getWidth() - text_dimension.Width) / 2; else if (m_rtl) offset.X += (position.getWidth() - text_dimension.Width); if (vcenter) offset.Y += (position.getHeight() - text_dimension.Height) / 2; if (clip) { core::rect<s32> clippedRect(offset, text_dimension); clippedRect.clipAgainst(*clip); if (!clippedRect.isValid()) return; } } // ---- collect character locations const unsigned int text_size = text.size(); core::array<s32> indices(text_size); core::array<core::position2di> offsets(text_size); std::vector<bool> fallback(text_size); for (u32 i = 0; i<text_size; i++) { wchar_t c = text[i]; if (c == L'\r' || // Windows breaks c == L'\n' ) // Unix breaks { if(c==L'\r' && text[i+1]==L'\n') c = text[++i]; offset.Y += (int)(MaxHeight*m_scale); offset.X = position.UpperLeftCorner.X; if (hcenter) offset.X += (position.getWidth() - text_dimension.Width) >> 1; continue; } // if lineBreak bool use_fallback_font = false; const SFontArea &area = getAreaFromCharacter(c, &use_fallback_font); fallback[i] = use_fallback_font; offset.X += area.underhang; offsets.push_back(offset); // Invisible character. add something to the array anyway so that // indices from the various arrays remain in sync indices.push_back( Invisible.findFirst(c) < 0 ? area.spriteno : -1 ); offset.X += getCharWidth(area, fallback[i]); } // for i<text_size // ---- do the actual rendering const int indiceAmount = indices.size(); core::array< SGUISprite >& sprites = SpriteBank->getSprites(); core::array< core::rect<s32> >& positions = SpriteBank->getPositions(); core::array< SGUISprite >* fallback_sprites; core::array< core::rect<s32> >* fallback_positions; if(m_fallback_font!=NULL) { fallback_sprites = &m_fallback_font->SpriteBank->getSprites(); fallback_positions = &m_fallback_font->SpriteBank->getPositions(); } else { fallback_sprites = NULL; fallback_positions = NULL; } const int spriteAmount = sprites.size(); for (int n=0; n<indiceAmount; n++) { const int spriteID = indices[n]; if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue; if (indices[n] == -1) continue; //assert(sprites[spriteID].Frames.size() > 0); const int texID = (fallback[n] ? (*fallback_sprites)[spriteID].Frames[0].textureNumber : sprites[spriteID].Frames[0].textureNumber); core::rect<s32> source = (fallback[n] ? (*fallback_positions)[(*fallback_sprites)[spriteID].Frames[0].rectNumber] : positions[sprites[spriteID].Frames[0].rectNumber]); const TextureInfo& info = (fallback[n] ? (*(m_fallback_font->m_texture_files.find(texID))).second : (*(m_texture_files.find(texID))).second ); float char_scale = info.m_scale; core::dimension2d<s32> size = source.getSize(); float scale = (fallback[n] ? m_scale*m_fallback_font_scale : m_scale); size.Width = (int)(size.Width * scale * char_scale); size.Height = (int)(size.Height * scale * char_scale); // align vertically if character is smaller int y_shift = (size.Height < MaxHeight*m_scale ? (int)((MaxHeight*m_scale - size.Height)/2.0f) : 0); core::rect<s32> dest(offsets[n] + core::position2di(0, y_shift), size); video::ITexture* texture = (fallback[n] ? m_fallback_font->SpriteBank->getTexture(texID) : SpriteBank->getTexture(texID) ); /* if (fallback[n]) { Log::info("ScalableFont", "Using fallback font %s; source area is %d, %d; size %d, %d; dest = %d, %d", core::stringc(texture->getName()).c_str(), source.UpperLeftCorner.X, source.UpperLeftCorner.Y, source.getWidth(), source.getHeight(), offsets[n].X, offsets[n].Y); } */ if (texture == NULL) { // perform lazy loading if (fallback[n]) { m_fallback_font->lazyLoadTexture(texID); texture = m_fallback_font->SpriteBank->getTexture(texID); } else { lazyLoadTexture(texID); texture = SpriteBank->getTexture(texID); } if (texture == NULL) { Log::warn("ScalableFont", "Character not found in current font"); continue; // no such character } } if (m_black_border && charCollector == NULL) { // draw black border video::SColor black(color.getAlpha(),0,0,0); for (int x_delta=-2; x_delta<=2; x_delta++) { for (int y_delta=-2; y_delta<=2; y_delta++) { if (x_delta == 0 || y_delta == 0) continue; draw2DImage(texture, dest + core::position2d<s32>(x_delta, y_delta), source, clip, black, true); } } } if (fallback[n]) { // TODO: don't hardcode colors? video::SColor orange(color.getAlpha(), 255, 100, 0); video::SColor yellow(color.getAlpha(), 255, 220, 15); video::SColor title_colors[] = {orange, yellow, orange, yellow}; if (charCollector != NULL) { charCollector->collectChar(texture, dest, source, title_colors); } else { draw2DImage(texture, dest, source, clip, title_colors, true); } } else { if (charCollector != NULL) { video::SColor colors[] = { color, color, color, color }; charCollector->collectChar(texture, dest, source, colors); } else { draw2DImage(texture, dest, source, clip, color, true); } #ifdef FONT_DEBUG video::IVideoDriver* driver = GUIEngine::getDriver(); driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y), core::position2d<s32>(dest.UpperLeftCorner.X, dest.LowerRightCorner.Y), video::SColor(255, 255,0,0)); driver->draw2DLine(core::position2d<s32>(dest.LowerRightCorner.X, dest.LowerRightCorner.Y), core::position2d<s32>(dest.LowerRightCorner.X, dest.UpperLeftCorner.Y), video::SColor(255, 255,0,0)); driver->draw2DLine(core::position2d<s32>(dest.LowerRightCorner.X, dest.LowerRightCorner.Y), core::position2d<s32>(dest.UpperLeftCorner.X, dest.LowerRightCorner.Y), video::SColor(255, 255,0,0)); driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y), core::position2d<s32>(dest.LowerRightCorner.X, dest.UpperLeftCorner.Y), video::SColor(255, 255,0,0)); #endif } } }
void STKMeshSceneNode::render() { irr::video::IVideoDriver* driver = irr_driver->getVideoDriver(); if (!Mesh || !driver) return; ++PassCount; updateNoGL(); updateGL(); bool isTransparent; for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); if (!mb) continue; video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType; video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type); isTransparent = rnd->isTransparent(); break; } if ((irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS) && immediate_draw && !isTransparent) { core::matrix4 invmodel; AbsoluteTransformation.getInverse(invmodel); glDisable(GL_CULL_FACE); if (update_each_frame) updatevbo(); glUseProgram(MeshShader::ObjectPass1Shader::getInstance()->Program); // Only untextured for (unsigned i = 0; i < GLmeshes.size(); i++) { irr_driver->IncreaseObjectCount(); GLMesh &mesh = GLmeshes[i]; GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; compressTexture(mesh.textures[0], true); if (UserConfigParams::m_azdo) { if (!mesh.TextureHandles[0]) mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]); if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0])) glMakeTextureHandleResidentARB(mesh.TextureHandles[0]); MeshShader::ObjectPass1Shader::getInstance()->SetTextureHandles(createVector<uint64_t>(mesh.TextureHandles[0])); } else MeshShader::ObjectPass1Shader::getInstance()->SetTextureUnits(std::vector < GLuint > { getTextureGLuint(mesh.textures[0]) }); MeshShader::ObjectPass1Shader::getInstance()->setUniforms(AbsoluteTransformation, invmodel); assert(mesh.vao); glBindVertexArray(mesh.vao); glDrawElements(ptype, count, itype, 0); glBindVertexArray(0); } glEnable(GL_CULL_FACE); return; } if (irr_driver->getPhase() == SOLID_LIT_PASS && immediate_draw && !isTransparent) { core::matrix4 invmodel; AbsoluteTransformation.getInverse(invmodel); glDisable(GL_CULL_FACE); if (update_each_frame && !UserConfigParams::m_dynamic_lights) updatevbo(); glUseProgram(MeshShader::ObjectPass2Shader::getInstance()->Program); // Only untextured for (unsigned i = 0; i < GLmeshes.size(); i++) { irr_driver->IncreaseObjectCount(); GLMesh &mesh = GLmeshes[i]; GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; if (UserConfigParams::m_azdo) { GLuint64 DiffuseHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_DIFFUSE), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[0]); if (!glIsTextureHandleResidentARB(DiffuseHandle)) glMakeTextureHandleResidentARB(DiffuseHandle); GLuint64 SpecularHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_SPECULAR), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[1]); if (!glIsTextureHandleResidentARB(SpecularHandle)) glMakeTextureHandleResidentARB(SpecularHandle); GLuint64 SSAOHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_HALF1_R), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[2]); if (!glIsTextureHandleResidentARB(SSAOHandle)) glMakeTextureHandleResidentARB(SSAOHandle); if (!mesh.TextureHandles[0]) mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]); if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0])) glMakeTextureHandleResidentARB(mesh.TextureHandles[0]); MeshShader::ObjectPass2Shader::getInstance()->SetTextureHandles(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, mesh.TextureHandles[0])); } else MeshShader::ObjectPass2Shader::getInstance()->SetTextureUnits(createVector<GLuint>( irr_driver->getRenderTargetTexture(RTT_DIFFUSE), irr_driver->getRenderTargetTexture(RTT_SPECULAR), irr_driver->getRenderTargetTexture(RTT_HALF1_R), getTextureGLuint(mesh.textures[0]))); MeshShader::ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix); assert(mesh.vao); glBindVertexArray(mesh.vao); glDrawElements(ptype, count, itype, 0); glBindVertexArray(0); } glEnable(GL_CULL_FACE); return; } if (irr_driver->getPhase() == GLOW_PASS) { glUseProgram(MeshShader::ColorizeShader::getInstance()->Program); for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); if (!mb) continue; if (irr_driver->hasARB_base_instance()) glBindVertexArray(VAOManager::getInstance()->getVAO(video::EVT_STANDARD)); else glBindVertexArray(GLmeshes[i].vao); drawGlow(GLmeshes[i]); } } if (irr_driver->getPhase() == TRANSPARENT_PASS && isTransparent) { ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation); if (immediate_draw) { if (update_each_frame) updatevbo(); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); if (World::getWorld() && World::getWorld()->isFogEnabled()) { glUseProgram(MeshShader::TransparentFogShader::getInstance()->Program); for (unsigned i = 0; i < GLmeshes.size(); i++) { GLMesh &mesh = GLmeshes[i]; irr_driver->IncreaseObjectCount(); GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; const Track * const track = World::getWorld()->getTrack(); // This function is only called once per frame - thus no need for setters. const float fogmax = track->getFogMax(); const float startH = track->getFogStartHeight(); const float endH = track->getFogEndHeight(); const float start = track->getFogStart(); const float end = track->getFogEnd(); const video::SColor tmpcol = track->getFogColor(); video::SColorf col(tmpcol.getRed() / 255.0f, tmpcol.getGreen() / 255.0f, tmpcol.getBlue() / 255.0f); compressTexture(mesh.textures[0], true); if (UserConfigParams::m_azdo) { if (!mesh.TextureHandles[0]) mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]); if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0])) glMakeTextureHandleResidentARB(mesh.TextureHandles[0]); MeshShader::TransparentFogShader::getInstance()->SetTextureHandles(createVector<uint64_t>(mesh.TextureHandles[0])); } else MeshShader::TransparentFogShader::getInstance()->SetTextureUnits(std::vector<GLuint>{ getTextureGLuint(mesh.textures[0]) }); MeshShader::TransparentFogShader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix, fogmax, startH, endH, start, end, col); assert(mesh.vao); glBindVertexArray(mesh.vao); glDrawElements(ptype, count, itype, 0); glBindVertexArray(0); } } else { glUseProgram(MeshShader::TransparentShader::getInstance()->Program); for (unsigned i = 0; i < GLmeshes.size(); i++) { irr_driver->IncreaseObjectCount(); GLMesh &mesh = GLmeshes[i]; GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; compressTexture(mesh.textures[0], true); if (UserConfigParams::m_azdo) { if (!mesh.TextureHandles[0]) mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentShader::getInstance()->SamplersId[0]); if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0])) glMakeTextureHandleResidentARB(mesh.TextureHandles[0]); MeshShader::TransparentShader::getInstance()->SetTextureHandles(createVector<uint64_t>(mesh.TextureHandles[0])); } else MeshShader::TransparentShader::getInstance()->SetTextureUnits(std::vector<GLuint>{ getTextureGLuint(mesh.textures[0]) }); MeshShader::TransparentShader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix); assert(mesh.vao); glBindVertexArray(mesh.vao); glDrawElements(ptype, count, itype, 0); glBindVertexArray(0); } } return; } } }
// ---------------------------------------------------------------------------- void DrawCalls::handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *ImmediateDraw, const scene::ICameraSceneNode *cam, ShadowMatrices& shadow_matrices) { STKMeshCommon* node = dynamic_cast<STKMeshCommon*>(Node); if (!node) return; node->updateNoGL(); m_deferred_update.push_back(node); if (node->isImmediateDraw()) { ImmediateDraw->push_back(Node); return; } bool culled_for_cams[6] = { true, true, true, true, true, true }; culled_for_cams[0] = isCulledPrecise(cam, Node, irr_driver->getBoundingBoxesViz()); if (UserConfigParams::m_gi && !shadow_matrices.isRSMMapAvail()) { culled_for_cams[1] = isCulledPrecise(shadow_matrices.getSunCam(), Node); } if (CVS->isShadowEnabled()) { for (unsigned i = 0; i < 4; i++) { culled_for_cams[i + 2] = isCulledPrecise(shadow_matrices.getShadowCamNodes()[i], Node); } } // Transparent if (World::getWorld() && World::getWorld()->isFogEnabled()) { const Track * const track = World::getWorld()->getTrack(); // Todo : put everything in a ubo const float fogmax = track->getFogMax(); const float startH = track->getFogStartHeight(); const float endH = track->getFogEndHeight(); const float start = track->getFogStart(); const float end = track->getFogEnd(); const video::SColor tmpcol = track->getFogColor(); video::SColorf col(tmpcol.getRed() / 255.0f, tmpcol.getGreen() / 255.0f, tmpcol.getBlue() / 255.0f); for (GLMesh *mesh : node->TransparentMesh[TM_DEFAULT]) pushVector(ListBlendTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, fogmax, startH, endH, start, end, col); for (GLMesh *mesh : node->TransparentMesh[TM_ADDITIVE]) pushVector(ListAdditiveTransparentFog::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, fogmax, startH, endH, start, end, col); } else { for (GLMesh *mesh : node->TransparentMesh[TM_DEFAULT]) pushVector(ListBlendTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, 1.0f); for (GLMesh *mesh : node->TransparentMesh[TM_ADDITIVE]) pushVector(ListAdditiveTransparent::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, 1.0f); } // Use sun color to determine custom alpha for ghost karts float custom_alpha = 1.0f; if (World::getWorld()) { const video::SColor& c = World::getWorld()->getTrack()->getSunColor(); float y = 0.2126f * c.getRed() + 0.7152f * c.getGreen() + 0.0722f * c.getBlue(); custom_alpha = y > 128.0f ? 0.5f : 0.35f; } for (GLMesh *mesh : node->TransparentMesh[TM_TRANSLUCENT_STD]) pushVector(ListTranslucentStandard::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, custom_alpha); for (GLMesh *mesh : node->TransparentMesh[TM_TRANSLUCENT_TAN]) pushVector(ListTranslucentTangents::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, custom_alpha); for (GLMesh *mesh : node->TransparentMesh[TM_TRANSLUCENT_2TC]) pushVector(ListTranslucent2TCoords::getInstance(), mesh, Node->getAbsoluteTransformation(), mesh->texture_trans, custom_alpha); for (GLMesh *mesh : node->TransparentMesh[TM_DISPLACEMENT]) pushVector(ListDisplacement::getInstance(), mesh, Node->getAbsoluteTransformation()); if (!culled_for_cams[0]) { for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat) { if (CVS->supportsIndirectInstancingRendering()) { for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { if (node->glow()) { m_glow_pass_mesh[mesh->mb].m_mesh = mesh; m_glow_pass_mesh[mesh->mb].m_instance_settings .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f)); } if (Mat == Material::SHADERTYPE_SPLATTING) { // Notice: splatting will be drawn using non-instanced shader only // It's only used one place (in overworld) and may be removed eventually core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; ModelMatrix.getInverse(InvModelMatrix); ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix); } else { // Only take render info into account if the node is not static (animated) // So they can have different animation std::pair<scene::IMeshBuffer*, RenderInfo*> mesh_render_info(mesh->mb, dynamic_cast<STKMeshSceneNode*>(Node) == NULL ? mesh->m_render_info : NULL); m_solid_pass_mesh[Mat][mesh_render_info].m_mesh = mesh; m_solid_pass_mesh[Mat][mesh_render_info].m_instance_settings.emplace_back(Node, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); } } } else { core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; ModelMatrix.getInverse(InvModelMatrix); for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { switch (Mat) { case Material::SHADERTYPE_SOLID: ListMatDefault::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; case Material::SHADERTYPE_ALPHA_TEST: ListMatAlphaRef::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; case Material::SHADERTYPE_NORMAL_MAP: ListMatNormalMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; case Material::SHADERTYPE_DETAIL_MAP: ListMatDetails::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SOLID_UNLIT: ListMatUnlit::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPHERE_MAP: ListMatSphereMap::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPLATTING: ListMatSplatting::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix); break; case Material::SHADERTYPE_VEGETATION: ListMatGrass::getInstance()->SolidPass.emplace_back(mesh, ModelMatrix, InvModelMatrix, m_wind_dir, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; case Material::SHADERTYPE_ALPHA_BLEND: break; case Material::SHADERTYPE_ADDITIVE: break; case Material::SHADERTYPE_WATER: break; default: Log::warn("DrawCalls", "Unknown material type: %d", Mat); } } } } } if (!CVS->isShadowEnabled()) return; for (unsigned cascade = 0; cascade < 4; ++cascade) { if (culled_for_cams[cascade + 2]) continue; for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat) { if (CVS->supportsIndirectInstancingRendering()) { for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_mesh = mesh; m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_instance_settings .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f)); } } else { core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; ModelMatrix.getInverse(InvModelMatrix); for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { switch (Mat) { case Material::SHADERTYPE_SOLID: ListMatDefault::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_ALPHA_TEST: ListMatAlphaRef::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_NORMAL_MAP: ListMatNormalMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_DETAIL_MAP: ListMatDetails::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SOLID_UNLIT: ListMatUnlit::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPHERE_MAP: ListMatSphereMap::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPLATTING: ListMatSplatting::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix); break; case Material::SHADERTYPE_VEGETATION: ListMatGrass::getInstance()->Shadows[cascade].emplace_back(mesh, ModelMatrix, InvModelMatrix, m_wind_dir, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); case Material::SHADERTYPE_ALPHA_BLEND: break; case Material::SHADERTYPE_ADDITIVE: break; case Material::SHADERTYPE_WATER: break; default: Log::warn("DrawCalls", "Unknown material type: %d", Mat); } } } } } if (!UserConfigParams::m_gi || shadow_matrices.isRSMMapAvail()) return; if (!culled_for_cams[1]) { for (unsigned Mat = 0; Mat < Material::SHADERTYPE_COUNT; ++Mat) { if (CVS->supportsIndirectInstancingRendering()) { for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { if (Mat == Material::SHADERTYPE_SPLATTING) { core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; ModelMatrix.getInverse(InvModelMatrix); ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix); } else { m_reflective_shadow_map_mesh[Mat][mesh->mb].m_mesh = mesh; m_reflective_shadow_map_mesh[Mat][mesh->mb].m_instance_settings .emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f)); } } } else { core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix; ModelMatrix.getInverse(InvModelMatrix); for (GLMesh *mesh : node->MeshSolidMaterial[Mat]) { switch (Mat) { case Material::SHADERTYPE_SOLID: ListMatDefault::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_ALPHA_TEST: ListMatAlphaRef::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_NORMAL_MAP: ListMatNormalMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans, core::vector2df(0.0f, 0.0f)); break; case Material::SHADERTYPE_DETAIL_MAP: ListMatDetails::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SOLID_UNLIT: ListMatUnlit::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPHERE_MAP: ListMatSphereMap::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, mesh->texture_trans); break; case Material::SHADERTYPE_SPLATTING: ListMatSplatting::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix); break; case Material::SHADERTYPE_VEGETATION: ListMatGrass::getInstance()->RSM.emplace_back(mesh, ModelMatrix, InvModelMatrix, m_wind_dir, (mesh->m_render_info && mesh->m_material ? core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) : core::vector2df(0.0f, 0.0f))); break; case Material::SHADERTYPE_ALPHA_BLEND: break; case Material::SHADERTYPE_ADDITIVE: break; case Material::SHADERTYPE_WATER: break; default: Log::warn("DrawCalls", "Unknown material type: %d", Mat); } } } } } }
static void applyFacesShading(video::SColor& color, float factor) { color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255)); color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255)); color.setBlue(core::clamp(core::round32(color.getBlue()*factor), 0, 255)); }
/** Used for drawing the background of dialogs and windows. \param element: Pointer to the element which whiches to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param titleBarColor: Title color. \param drawTitleBar: True to enable title drawing. \param rect: Defining area where to draw. \param clip: Clip area. \return Returns rect where to draw title bar text. */ core::rect<s32> CGUISkin::draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect<s32>& r, const core::rect<s32>* cl) { if (!Driver) return r; core::rect<s32> rect = r; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, cl); rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, cl); rect.UpperLeftCorner.X = r.LowerRightCorner.X - 1; rect.LowerRightCorner.X = r.LowerRightCorner.X; rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, cl); rect.UpperLeftCorner.X -= 1; rect.LowerRightCorner.X -= 1; rect.UpperLeftCorner.Y += 1; rect.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, cl); rect.UpperLeftCorner.X = r.UpperLeftCorner.X; rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = r.LowerRightCorner.X; Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, cl); rect.UpperLeftCorner.X += 1; rect.LowerRightCorner.X -= 1; rect.UpperLeftCorner.Y -= 1; rect.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, cl); rect = r; rect.UpperLeftCorner.X +=1; rect.UpperLeftCorner.Y +=1; rect.LowerRightCorner.X -= 2; rect.LowerRightCorner.Y -= 2; if (!UseGradient) Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, cl); else { video::SColor c2 = getColor(EGDC_3D_SHADOW); video::SColor c1 = getColor(EGDC_3D_FACE); Driver->draw2DRectangle(rect, c1, c1, c1, c2, cl); } rect = r; rect.UpperLeftCorner.X += 2; rect.UpperLeftCorner.Y += 2; rect.LowerRightCorner.X -= 2; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + getSize(EGDS_WINDOW_BUTTON_WIDTH) + 2; if (drawTitleBar) { // draw title bar //if (!UseGradient) // Driver->draw2DRectangle(titleBarColor, rect, cl); //else { video::SColor c = titleBarColor.getInterpolated(video::SColor(255,0,0,0), 0.2f); Driver->draw2DRectangle(rect, titleBarColor, c, titleBarColor, c, cl); } } return rect; }