void Material_DrawFullscreenQuad(MaterialObj* material) { const float uv[8] = { 0, 0, 1, 0, 1, 1, 0, 1 }; float xy[8] = { -1, 1, 1, 1, 1, -1, -1, -1 }; if (App::GetCurrentRenderTarget() != App::GetMainRenderTarget()) for (int i = 1; i < 8; i += 2) xy[i] = -xy[i]; Shape::DrawParams params; params.SetNumVerts(4); params.SetPosition(xy); params.SetTexCoord(uv); Material_Draw(material, ¶ms); }
void Shape::DrawRectangle(const Rect& rect, float rotation, const Color& color) { float xy[] = { rect.left, rect.top, rect.left + rect.width, rect.top, rect.left + rect.width, rect.top + rect.height, rect.left, rect.top + rect.height }; if (rotation != 0) { const float centerX = rect.left + rect.width * 0.5f; const float centerY = rect.top + rect.height * 0.5f; const float rotationSin = sinf(rotation); const float rotationCos = cosf(rotation); for (unsigned int i = 0; i < 4 * 2; i += 2) Vertex_Rotate(xy[i], xy[i + 1], centerX, centerY, rotationSin, rotationCos); } Shape::DrawParams params; params.color = color; params.SetNumVerts(4); params.SetGeometryType(Geometry::Type_TriangleFan); params.SetPosition(xy); Shape::Draw(¶ms); }
void Shape::DrawLines(const Vec2* xy, int count, const Color& color) { Shape::DrawParams params; params.color = color; params.SetNumVerts(count * 2); params.SetGeometryType(Geometry::Type_Lines); params.SetPosition(xy); Shape::Draw(¶ms); }
void Shape::DrawLine(const Vec2& point0, const Vec2& point1, const Color& color) { const Vec2 points[] = {point0, point1}; Shape::DrawParams params; params.color = color; params.SetNumVerts(2); params.SetGeometryType(Geometry::Type_Lines); params.SetPosition(points); Shape::Draw(¶ms); }
void Shape::DrawCircle(const Vec2& center, float radius, int numSegments, float rotation, const Color& color) { std::vector<Vec2> xy(numSegments); float angle = rotation; const float angleStep = 3.141592654f * 2.0f / (float) numSegments; for (unsigned int i = 0; i < xy.size(); i++) { xy[i] = Vec2( sinf(angle) * radius + center.x, cosf(angle) * radius + center.y); angle += angleStep; } Shape::DrawParams params; params.color = color; params.SetNumVerts(numSegments); params.SetGeometryType(Geometry::Type_TriangleFan); params.SetPosition(&xy[0]); Shape::Draw(¶ms); }
void Font_Draw(FontObj* font, const Text::DrawParams* params) { // Convert to UTF32 unsigned int buffer[1024]; unsigned int bufferSize = ARRAYSIZE(buffer); if (!UTF8ToUTF32((const unsigned char*) params->text.c_str(), params->text.length(), buffer, bufferSize)) return; // Make sure all glyphs are present Font_CacheGlyphs(font, buffer, bufferSize); // Generate positions and uvs for the text if (!font->texture) return; const float scale = params->scale; std::vector<float> xy; std::vector<float> uv; float x = params->position.x; float y = params->position.y; for (unsigned int i = 0; i < bufferSize; i++) { if (buffer[i] == '\r') continue; if (buffer[i] == '\n') { y += (float) font->size * scale; x = params->position.x; continue; } Glyph* glyph = map_find(font->glyphs, buffer[i]); if (!glyph) continue; uv.push_back(glyph->uv.left); uv.push_back(glyph->uv.top); uv.push_back(glyph->uv.left + glyph->uv.width); uv.push_back(glyph->uv.top); uv.push_back(glyph->uv.left + glyph->uv.width); uv.push_back(glyph->uv.top + glyph->uv.height); uv.push_back(glyph->uv.left); uv.push_back(glyph->uv.top + glyph->uv.height); uv.push_back(*(uv.end() - 8)); uv.push_back(*(uv.end() - 8)); uv.push_back(*(uv.end() - 6)); uv.push_back(*(uv.end() - 6)); xy.push_back(x + glyph->pos.left * scale); xy.push_back(y + glyph->pos.top * scale); xy.push_back(x + (glyph->pos.left + glyph->pos.width) * scale); xy.push_back(y + glyph->pos.top * scale); xy.push_back(x + (glyph->pos.left + glyph->pos.width) * scale); xy.push_back(y + (glyph->pos.top + glyph->pos.height) * scale); xy.push_back(x + glyph->pos.left * scale); xy.push_back(y + (glyph->pos.top + glyph->pos.height) * scale); xy.push_back(*(xy.end() - 8)); xy.push_back(*(xy.end() - 8)); xy.push_back(*(xy.end() - 6)); xy.push_back(*(xy.end() - 6)); x += glyph->advancePos * scale; } // Determine mins and maxes of the text float minX = (float) INT_MAX, maxX = (float) INT_MIN, minY = (float) INT_MAX, maxY = (float) INT_MIN; for (unsigned int i = 0; i < xy.size(); i += 2) { minX = min(minX, xy[i]); maxX = max(maxX, xy[i]); minY = min(minY, xy[i + 1]); maxY = max(maxY, xy[i + 1]); } // Determine the center of the text float centerX = 0.0f, centerY = 0.0f; if (params->width == 0.0f || params->height == 0.0f) { centerX = (minX + maxX) * 0.5f; centerY = (minY + maxY) * 0.5f; } else { centerX = params->position.x + params->width * 0.5f; centerY = params->position.y + params->height * 0.5f; } // Align the text switch (params->horizontalAlignment) { case Text::HorizontalAlignment_Center: { const float offset = params->position.x + params->width * 0.5f - (minX + maxX) * 0.5f; for (unsigned int i = 0; i < xy.size(); i += 2) xy[i] += offset; break; } case Text::HorizontalAlignment_Right: { const float offset = params->position.x + params->width - maxX; for (unsigned int i = 0; i < xy.size(); i += 2) xy[i] += offset; break; } default: //case Text::HorizontalAlignment_Left : break; } switch (params->verticalAlignment) { case Text::VerticalAlignment_Center: { const float offset = params->position.y + params->height * 0.5f - (minY + maxY) * 0.5f; for (unsigned int i = 1; i < xy.size(); i += 2) xy[i] += offset; break; } case Text::VerticalAlignment_Bottom: { const float offset = params->position.y + params->height - maxY; for (unsigned int i = 1; i < xy.size(); i += 2) xy[i] += offset; break; } default: //case Text::VerticalAlignment_Top: break; } // Set up draw params Shape::DrawParams texParams; texParams.SetGeometryType(Shape::Geometry::Type_Triangles); texParams.SetNumVerts(xy.size() / 2); texParams.SetTexCoord(&uv[0]); // Draw shadow if (params->drawShadow) { // Offset verts for the shadow rendering std::vector<float> xyShadow = xy; for (unsigned int i = 0; i < xyShadow.size(); i += 2) { xyShadow[i] += params->shadowOffset.x; xyShadow[i + 1] += params->shadowOffset.y; } // Rotate the shadow text if (params->rotation != 0) { const float rotationSin = sinf(params->rotation); const float rotationCos = cosf(params->rotation); for (unsigned int i = 0; i < xyShadow.size(); i += 2) Vertex_Rotate(xyShadow[i], xyShadow[i + 1], centerX, centerY, rotationSin, rotationCos); } // Draw the shadow texParams.color = params->shadowColor; texParams.SetPosition(&xyShadow[0]); Texture_Draw(font->texture, &texParams); } // Rotate the text if (params->rotation != 0) { const float rotationSin = sinf(params->rotation); const float rotationCos = cosf(params->rotation); for (unsigned int i = 0; i < xy.size(); i += 2) Vertex_Rotate(xy[i], xy[i + 1], centerX, centerY, rotationSin, rotationCos); } // Draw texParams.color = params->color; texParams.SetPosition(&xy[0]); Texture_Draw(font->texture, &texParams); }
void Postprocessing_DrawRainyGlass(Texture& renderTarget, Texture& scene) { Texture dropletTarget = RenderTexturePool::Get(256, 256); // Clear droplet render target to default front-facing direction const Color frontClearColor(0.5f /* x == 0 */, 0.5f /* y = 0 */, 1.0f /* z = 1 */, 0.0f); dropletTarget.BeginDrawing(&frontClearColor); // Evaporation if (rain->dropletBuffer.IsValid()) { if (rain->rainEvaporation > 0.02f) // Apply rain evaporation { rain->material.SetTechnique("rain_evaporation"); rain->rainEvaporation = 0; } else // Just copy previous buffer (skip evaporation step this time) { rain->material.SetTechnique("copy_texture"); } rain->material.SetTextureParameter("ColorMap", rain->dropletBuffer, Sampler::DefaultPostprocess); rain->material.DrawFullscreenQuad(); } // Droplets const Vec2 sizeScale( (float) dropletTarget.GetWidth(), (float) dropletTarget.GetHeight() ); while (rain->deltaTime > 0.0f) { const float stepDeltaTime = min(rain->deltaTime, 1 / 60.0f); rain->deltaTime -= stepDeltaTime; Postprocessing_UpdateRainyGlassStep(stepDeltaTime); const unsigned int numDroplets = rain->droplets.size(); if (!numDroplets) continue; std::vector<Vec2> verts(numDroplets * 4); std::vector<Vec2> tex(numDroplets * 4); std::vector<unsigned short> indices(numDroplets * 6); int currVertexIndex = 0; unsigned short* currIndex = &indices[0]; std::vector<RainyGlass::Droplet>::iterator dropletsEnd = rain->droplets.end(); for (std::vector<RainyGlass::Droplet>::iterator it = rain->droplets.begin(); it != dropletsEnd; ++it) { Vec2 size = Vec2(it->size, it->size); Vec2 pos = it->pos - size * 0.5f; size *= sizeScale; pos *= sizeScale; Vec2* currVertex = &verts[currVertexIndex]; *(currVertex++) = pos; *(currVertex++) = pos + Vec2(size.x, 0.0f); *(currVertex++) = pos + size; *(currVertex++) = pos + Vec2(0.0f, size.y); Vec2* currTex = &tex[currVertexIndex]; (currTex++)->Set(0.0f, 0.0f); (currTex++)->Set(1.0f, 0.0f); (currTex++)->Set(1.0f, 1.0f); (currTex++)->Set(0.0f, 1.0f); *(currIndex++) = currVertexIndex; *(currIndex++) = currVertexIndex + 1; *(currIndex++) = currVertexIndex + 2; *(currIndex++) = currVertexIndex; *(currIndex++) = currVertexIndex + 2; *(currIndex++) = currVertexIndex + 3; currVertexIndex += 4; } Shape::DrawParams drawParams; drawParams.SetGeometryType(Shape::Geometry::Type_Triangles); drawParams.SetNumVerts(verts.size()); drawParams.SetPosition(&verts[0], sizeof(Vec2)); drawParams.SetTexCoord(&tex[0], 0, sizeof(Vec2)); drawParams.SetIndices(indices.size(), &indices[0]); Material& defaultMaterial = App::GetDefaultMaterial(); defaultMaterial.SetTechnique("tex_col"); defaultMaterial.SetFloatParameter("Color", (const float*) &Color::White, 4); defaultMaterial.SetTextureParameter("ColorMap", rain->dropletTexture); defaultMaterial.Draw(&drawParams); } dropletTarget.EndDrawing(); // Swap droplet buffer if (rain->dropletBuffer.IsValid()) RenderTexturePool::Release(rain->dropletBuffer); rain->dropletBuffer = dropletTarget; // Apply droplet buffer distortion to scene renderTarget.BeginDrawing(); Sampler colorSampler = Sampler::DefaultPostprocess; colorSampler.minFilterLinear = true; colorSampler.magFilterLinear = true; rain->material.SetTechnique("rain_distortion"); rain->material.SetFloatParameter("DropletColor", (const float*) &rain->dropletColor, 4); rain->material.SetTextureParameter("ColorMap", scene, colorSampler); rain->material.SetTextureParameter("NormalMap", rain->dropletBuffer); rain->material.DrawFullscreenQuad(); renderTarget.EndDrawing(); }
void Sprite_Draw(SpriteObj* sprite, const Sprite::DrawParams* params) { if (!SpriteResource_CheckCreated(sprite->resource)) return; // Get animation instance SpriteObj::AnimationInstance* animationInstance = NULL; for (std::vector<SpriteObj::AnimationInstance>::iterator it = sprite->animationInstances.begin(); it != sprite->animationInstances.end(); ++it) if (it->mode != Sprite::AnimationMode_OnceWhenDone && it->mode != Sprite::AnimationMode_LoopWhenDone && (!animationInstance || it->weight > animationInstance->weight)) animationInstance = &(*it); Assert(animationInstance); // Determine textures to draw Texture* texture0 = NULL; Texture* texture1 = NULL; Shape::DrawParams texParams; float lerp = 0.0f; float uv[8] = { 0, 0, 1, 0, 1, 1, 0, 1 }; if (params->texCoordRect) { uv[0] = params->texCoordRect->left; uv[1] = params->texCoordRect->top; uv[2] = params->texCoordRect->Right(); uv[3] = params->texCoordRect->top; uv[4] = params->texCoordRect->Right(); uv[5] = params->texCoordRect->Bottom(); uv[6] = params->texCoordRect->left; uv[7] = params->texCoordRect->Bottom(); } if (params->flipX) for (int i = 0; i < 8; i += 2) uv[i] = 1.0f - uv[i]; if (params->flipY) for (int i = 1; i < 8; i += 2) uv[i] = 1.0f - uv[i]; SpriteResource::Animation* animation = animationInstance->animation; if (animation->frames.size() == 1) { texture0 = &animation->frames[0].texture; texParams.color = params->color; texParams.SetNumVerts(4); texParams.SetTexCoord(uv); } else { const float numFramesF = (float) animation->frames.size(); const float frameIndexF = numFramesF * (animationInstance->time / animation->totalTime); const float firstFrameIndexF = floorf(frameIndexF); const int firstFrameIndex = clamp((int) firstFrameIndexF, (int) 0, (int) animation->frames.size() - 1); const int nextFrameIndex = (firstFrameIndex + 1) % animation->frames.size(); SpriteResource::Frame& firstFrame = animation->frames[firstFrameIndex]; SpriteResource::Frame& nextFrame = animation->frames[nextFrameIndex]; texture0 = &firstFrame.texture; texture1 = &nextFrame.texture; texParams.SetNumVerts(4); texParams.SetTexCoord(uv, 0); texParams.SetTexCoord(uv, 1); lerp = frameIndexF - firstFrameIndexF; } float xy[8] = { params->position.x, params->position.y, params->position.x + sprite->resource->width * params->scale, params->position.y, params->position.x + sprite->resource->width * params->scale, params->position.y + sprite->resource->height * params->scale, params->position.x, params->position.y + sprite->resource->height * params->scale }; if (params->rect) { xy[0] = params->rect->left; xy[1] = params->rect->top; xy[2] = params->rect->Right(); xy[3] = params->rect->top; xy[4] = params->rect->Right(); xy[5] = params->rect->Bottom(); xy[6] = params->rect->left; xy[7] = params->rect->Bottom(); } if (params->rotation != 0) { const float centerX = (xy[0] + xy[2]) * 0.5f; const float centerY = (xy[1] + xy[5]) * 0.5f; const float rotationSin = sinf(params->rotation); const float rotationCos = cosf(params->rotation); float* xyPtr = xy; for (int i = 0; i < 4; i++, xyPtr += 2) Vertex_Rotate(xyPtr[0], xyPtr[1], centerX, centerY, rotationSin, rotationCos); } texParams.SetPosition(xy); // Draw #if 0 if (texture1) Texture_DrawBlended(texture0, texture1, &texParams, lerp); else Texture_Draw(texture0, &texParams); #else Material* material = &sprite->resource->material; if (!material->IsValid()) material = &App::GetDefaultMaterial(); material->SetFloatParameter("Color", (const float*) &texParams.color, 4); if (texture1) { material->SetTechnique("tex_lerp_col"); material->SetTextureParameter("ColorMap0", *texture0); material->SetTextureParameter("ColorMap1", *texture1); material->SetFloatParameter("Scale", &lerp); material->Draw(&texParams); } else { material->SetTechnique("tex_col"); material->SetTextureParameter("ColorMap", *texture0); material->Draw(&texParams); } #endif }