1 /* 2 Copyright (c) 2013 yvt 3 4 This file is part of OpenSpades. 5 6 OpenSpades is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 OpenSpades is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with OpenSpades. If not, see <http://www.gnu.org/licenses/>. 18 19 */ 20 21 #include "GLSpriteRenderer.h" 22 #include <Core/Debug.h> 23 #include "GLImage.h" 24 #include "GLProgram.h" 25 #include "GLRenderer.h" 26 #include "IGLDevice.h" 27 #include "SWFeatureLevel.h" 28 29 namespace spades { 30 namespace draw { 31 GLSpriteRenderer(GLRenderer * renderer)32 GLSpriteRenderer::GLSpriteRenderer(GLRenderer *renderer) 33 : renderer(renderer), 34 device(renderer->GetGLDevice()), 35 settings(renderer->GetSettings()), 36 projectionViewMatrix("projectionViewMatrix"), 37 rightVector("rightVector"), 38 upVector("upVector"), 39 texture("mainTexture"), 40 viewMatrix("viewMatrix"), 41 fogDistance("fogDistance"), 42 fogColor("fogColor"), 43 viewOriginVector("viewOriginVector"), 44 positionAttribute("positionAttribute"), 45 spritePosAttribute("spritePosAttribute"), 46 colorAttribute("colorAttribute") { 47 SPADES_MARK_FUNCTION(); 48 49 program = renderer->RegisterProgram("Shaders/Sprite.program"); 50 } 51 ~GLSpriteRenderer()52 GLSpriteRenderer::~GLSpriteRenderer() { SPADES_MARK_FUNCTION(); } 53 Add(spades::draw::GLImage * img,spades::Vector3 center,float rad,float ang,Vector4 color)54 void GLSpriteRenderer::Add(spades::draw::GLImage *img, spades::Vector3 center, float rad, 55 float ang, Vector4 color) { 56 SPADES_MARK_FUNCTION_DEBUG(); 57 Sprite spr; 58 spr.image = img; 59 spr.center = center; 60 spr.radius = rad; 61 spr.angle = ang; 62 if (settings.r_hdr) { 63 // linearize color 64 if (color.x > color.w || color.y > color.w || color.z > color.w) { 65 // emissive material 66 color.x *= color.x; 67 color.y *= color.y; 68 color.z *= color.z; 69 } else { 70 // scattering/absorptive material 71 float rcp = fastRcp(color.w + .01); 72 color.x *= color.x * rcp; 73 color.y *= color.y * rcp; 74 color.z *= color.z * rcp; 75 } 76 } 77 spr.color = color; 78 sprites.push_back(spr); 79 } 80 Clear()81 void GLSpriteRenderer::Clear() { 82 SPADES_MARK_FUNCTION(); 83 sprites.clear(); 84 } 85 Render()86 void GLSpriteRenderer::Render() { 87 SPADES_MARK_FUNCTION(); 88 lastImage = NULL; 89 program->Use(); 90 91 projectionViewMatrix(program); 92 rightVector(program); 93 upVector(program); 94 texture(program); 95 viewMatrix(program); 96 fogDistance(program); 97 fogColor(program); 98 viewOriginVector(program); 99 100 positionAttribute(program); 101 spritePosAttribute(program); 102 colorAttribute(program); 103 104 projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); 105 viewMatrix.SetValue(renderer->GetViewMatrix()); 106 107 fogDistance.SetValue(renderer->GetFogDistance()); 108 109 const auto &viewOrigin = renderer->GetSceneDef().viewOrigin; 110 viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z); 111 112 Vector3 fogCol = renderer->GetFogColor(); 113 fogCol *= fogCol; 114 fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); 115 116 const client::SceneDefinition &def = renderer->GetSceneDef(); 117 rightVector.SetValue(def.viewAxis[0].x, def.viewAxis[0].y, def.viewAxis[0].z); 118 upVector.SetValue(def.viewAxis[1].x, def.viewAxis[1].y, def.viewAxis[1].z); 119 texture.SetValue(0); 120 121 device->ActiveTexture(0); 122 123 device->EnableVertexAttribArray(positionAttribute(), true); 124 device->EnableVertexAttribArray(spritePosAttribute(), true); 125 device->EnableVertexAttribArray(colorAttribute(), true); 126 127 for (size_t i = 0; i < sprites.size(); i++) { 128 Sprite &spr = sprites[i]; 129 if (spr.image != lastImage) { 130 Flush(); 131 lastImage = spr.image; 132 SPAssert(vertices.empty()); 133 } 134 135 Vertex v; 136 v.x = spr.center.x; 137 v.y = spr.center.y; 138 v.z = spr.center.z; 139 v.radius = spr.radius; 140 v.angle = spr.angle; 141 v.r = spr.color.x; 142 v.g = spr.color.y; 143 v.b = spr.color.z; 144 v.a = spr.color.w; 145 146 uint32_t idx = (uint32_t)vertices.size(); 147 v.sx = -1; 148 v.sy = -1; 149 vertices.push_back(v); 150 v.sx = 1; 151 v.sy = -1; 152 vertices.push_back(v); 153 v.sx = -1; 154 v.sy = 1; 155 vertices.push_back(v); 156 v.sx = 1; 157 v.sy = 1; 158 vertices.push_back(v); 159 160 indices.push_back(idx); 161 indices.push_back(idx + 1); 162 indices.push_back(idx + 2); 163 indices.push_back(idx + 1); 164 indices.push_back(idx + 3); 165 indices.push_back(idx + 2); 166 } 167 168 Flush(); 169 170 device->EnableVertexAttribArray(positionAttribute(), false); 171 device->EnableVertexAttribArray(spritePosAttribute(), false); 172 device->EnableVertexAttribArray(colorAttribute(), false); 173 } 174 Flush()175 void GLSpriteRenderer::Flush() { 176 SPADES_MARK_FUNCTION_DEBUG(); 177 178 if (vertices.empty()) 179 return; 180 181 device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::FloatType, false, 182 sizeof(Vertex), &(vertices[0].x)); 183 device->VertexAttribPointer(spritePosAttribute(), 4, IGLDevice::FloatType, false, 184 sizeof(Vertex), &(vertices[0].sx)); 185 device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::FloatType, false, 186 sizeof(Vertex), &(vertices[0].r)); 187 188 SPAssert(lastImage); 189 lastImage->Bind(IGLDevice::Texture2D); 190 191 device->DrawElements(IGLDevice::Triangles, 192 static_cast<IGLDevice::Sizei>(indices.size()), 193 IGLDevice::UnsignedInt, indices.data()); 194 195 vertices.clear(); 196 indices.clear(); 197 } 198 } 199 } 200