1 /* 2 Copyright (c) 2018 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 */ 27 28 module dagon.graphics.materials.particle; 29 30 import std.stdio; 31 import std.math; 32 import std.conv; 33 34 import dlib.core.memory; 35 import dlib.math.vector; 36 import dlib.math.matrix; 37 import dlib.image.color; 38 import dlib.image.unmanaged; 39 40 import derelict.opengl; 41 42 import dagon.core.ownership; 43 import dagon.graphics.rc; 44 import dagon.graphics.material; 45 import dagon.graphics.materials.generic; 46 47 /* 48 * Backend for particle systems 49 */ 50 51 class ParticleBackend: GLSLMaterialBackend 52 { 53 private string vsText = q{ 54 #version 330 core 55 56 layout (location = 0) in vec3 va_Vertex; 57 layout (location = 2) in vec2 va_Texcoord; 58 59 out vec3 eyePosition; 60 out vec2 texCoord; 61 62 uniform mat4 modelViewMatrix; 63 uniform mat4 projectionMatrix; 64 65 uniform mat4 invViewMatrix; 66 67 void main() 68 { 69 vec4 pos = modelViewMatrix * vec4(va_Vertex, 1.0); 70 eyePosition = pos.xyz; 71 72 texCoord = va_Texcoord; 73 gl_Position = projectionMatrix * pos; 74 } 75 }; 76 77 private string fsText = q{ 78 #version 330 core 79 80 uniform sampler2D diffuseTexture; 81 uniform vec4 particleColor; 82 uniform float alpha; 83 uniform float energy; 84 85 in vec3 eyePosition; 86 in vec2 texCoord; 87 88 layout(location = 0) out vec4 frag_color; 89 layout(location = 1) out vec4 frag_velocity; 90 layout(location = 2) out vec4 frag_luma; 91 layout(location = 3) out vec4 frag_position; 92 93 float luminance(vec3 color) 94 { 95 return ( 96 color.x * 0.27 + 97 color.y * 0.67 + 98 color.z * 0.06 99 ); 100 } 101 102 vec3 toLinear(vec3 v) 103 { 104 return pow(v, vec3(2.2)); 105 } 106 107 void main() 108 { 109 vec4 textureColor = texture(diffuseTexture, texCoord); 110 vec3 outColor = toLinear(textureColor.rgb) * toLinear(particleColor.rgb) * energy; 111 float outAlpha = textureColor.a * particleColor.a * alpha; 112 113 frag_color = vec4(outColor, outAlpha); 114 frag_luma = vec4(energy * outAlpha, 0.0, 0.0, 1.0); 115 frag_velocity = vec4(0.0, 0.0, 0.0, 1.0); 116 frag_position = vec4(eyePosition, 0.0); 117 } 118 }; 119 120 override string vertexShaderSrc() {return vsText;} 121 override string fragmentShaderSrc() {return fsText;} 122 123 GLint modelViewMatrixLoc; 124 GLint projectionMatrixLoc; 125 126 GLint diffuseTextureLoc; 127 GLint alphaLoc; 128 GLint energyLoc; 129 GLint particleColorLoc; 130 131 this(Owner o) 132 { 133 super(o); 134 135 modelViewMatrixLoc = glGetUniformLocation(shaderProgram, "modelViewMatrix"); 136 projectionMatrixLoc = glGetUniformLocation(shaderProgram, "projectionMatrix"); 137 138 diffuseTextureLoc = glGetUniformLocation(shaderProgram, "diffuseTexture"); 139 alphaLoc = glGetUniformLocation(shaderProgram, "alpha"); 140 energyLoc = glGetUniformLocation(shaderProgram, "energy"); 141 particleColorLoc = glGetUniformLocation(shaderProgram, "particleColor"); 142 } 143 144 override void bind(GenericMaterial mat, RenderingContext* rc) 145 { 146 auto idiffuse = "diffuse" in mat.inputs; 147 auto ienergy = "energy" in mat.inputs; 148 auto itransparency = "transparency" in mat.inputs; 149 auto iparticleColor = "particleColor" in mat.inputs; 150 151 float energy = ienergy.asFloat; 152 153 glUseProgram(shaderProgram); 154 155 // Matrices 156 glUniformMatrix4fv(modelViewMatrixLoc, 1, GL_FALSE, rc.modelViewMatrix.arrayof.ptr); 157 glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, rc.projectionMatrix.arrayof.ptr); 158 159 // Texture 0 - diffuse texture 160 Color4f particleColor = Color4f(1.0f, 1.0f, 1.0f, 1.0f); 161 Color4f color = Color4f(idiffuse.asVector4f); 162 float alpha = 1.0f; 163 164 if (idiffuse.texture is null) 165 { 166 idiffuse.texture = makeOnePixelTexture(mat, color); 167 } 168 169 if (itransparency) 170 { 171 alpha = itransparency.asFloat; 172 } 173 174 if (iparticleColor) 175 { 176 particleColor = Color4f(iparticleColor.asVector4f); 177 } 178 179 glActiveTexture(GL_TEXTURE0); 180 idiffuse.texture.bind(); 181 glUniform1i(diffuseTextureLoc, 0); 182 glUniform1f(alphaLoc, alpha); 183 glUniform1f(energyLoc, energy); 184 glUniform4fv(particleColorLoc, 1, particleColor.arrayof.ptr); 185 } 186 187 override void unbind(GenericMaterial mat, RenderingContext* rc) 188 { 189 auto idiffuse = "diffuse" in mat.inputs; 190 191 glActiveTexture(GL_TEXTURE0); 192 idiffuse.texture.unbind(); 193 194 glUseProgram(0); 195 } 196 }