1 module unecht.core.components.material; 2 3 import derelict.opengl3.gl3; 4 5 import gl3n.linalg; 6 7 import unecht.core.component; 8 import unecht.core.assets.texture; 9 10 import unecht.gl.shader; 11 import unecht.gl.program; 12 import unecht.gl.texture; 13 14 /// 15 struct GLMaterialUniforms 16 { 17 private GLProgram _program; 18 19 void setColor(in vec4 _v) 20 { 21 _program.bind(); 22 _program.setUniformVec4("globalColor", _v); 23 } 24 25 void setMatWorld(const ref mat4 _v) 26 { 27 _program.bind(); 28 _program.setUniformMatrix("matWorld", _v); 29 } 30 31 void setViewDir(in vec3 _v) 32 { 33 _program.bind(); 34 _program.setUniformVec3("v3ViewDir", _v); 35 } 36 } 37 38 /// 39 final class UEMaterial : UEComponent 40 { 41 mixin(UERegisterObject!()); 42 43 //TODO: remove shader hardwiring 44 static const string vs_shaded = cast(string)import("vs_shaded.glsl"); 45 static const string fs_shaded = cast(string)import("fs_shaded.glsl"); 46 47 static const string vs_tex = cast(string)import("vs_tex.glsl"); 48 static const string fs_tex = cast(string)import("fs_tex.glsl"); 49 50 static const string vs_flat = cast(string)import("vs_flat.glsl"); 51 static const string fs_flat = cast(string)import("fs_flat.glsl"); 52 53 static const string vs_flatcolor = cast(string)import("vs_flatcolor.glsl"); 54 static const string fs_flatcolor = cast(string)import("fs_flatcolor.glsl"); 55 56 /// 57 enum CullMode 58 { 59 cullNone, 60 cullFront, 61 cullBack 62 } 63 64 /// 65 @Serialize bool polygonFill = true; 66 /// 67 @Serialize bool depthTest = true; 68 /// 69 @Serialize CullMode cullMode = CullMode.cullNone; 70 /// 71 @Serialize UETexture2D texture; 72 73 /// 74 @property GLMaterialUniforms uniforms() { return GLMaterialUniforms(_program); } 75 /// 76 @property uint attribLocation(GLAtrribTypes _v) const { return _program.attribLocations[_v]; } 77 78 /// 79 override void onCreate() { 80 super.onCreate; 81 82 _program = new GLProgram(); 83 84 if(_vshader.length == 0 || _fshader.length == 0 || _shaderName.length == 0) 85 setProgram(vs_flat,fs_flat, "flat"); 86 else 87 setProgram(_vshader, _fshader, _shaderName); 88 } 89 90 /// 91 override void onDestroy() { 92 super.onDestroy; 93 94 if(_program) _program.destroy(); 95 96 _program = null; 97 texture = null; 98 } 99 100 /// 101 void setProgram(string _vs, string _fs, string _name) 102 { 103 import std.typecons:scoped; 104 105 _fshader = _fs; 106 _vshader = _vs; 107 _shaderName = _name; 108 109 auto vshader = scoped!GLShader(); 110 auto fshader = scoped!GLShader(); 111 scope(exit) vshader.destroy(); 112 scope(exit) fshader.destroy(); 113 114 vshader.create(ShaderType.vertex, _vshader); 115 fshader.create(ShaderType.fragment, _fshader); 116 117 _program.create(vshader,fshader, _name); 118 } 119 120 /// 121 void preRender() 122 { 123 glPolygonMode( GL_FRONT_AND_BACK, polygonFill ? GL_FILL : GL_LINE ); 124 125 if(depthTest) 126 { 127 glEnable(GL_DEPTH_TEST); 128 glDepthFunc(GL_LEQUAL); 129 glDepthMask(GL_TRUE); 130 } 131 else 132 glDisable(GL_DEPTH_TEST); 133 134 if(cullMode != CullMode.cullNone) 135 { 136 glEnable(GL_CULL_FACE); 137 glCullFace((cullMode == CullMode.cullFront) ? GL_FRONT : GL_BACK); 138 } 139 else 140 { 141 glDisable(GL_CULL_FACE); 142 } 143 144 if(texture) 145 { 146 glActiveTexture(GL_TEXTURE0); 147 texture.bind(); 148 } 149 150 _program.bind(); 151 } 152 153 /// 154 void postRender() 155 { 156 _program.unbind(); 157 158 if(texture) 159 { 160 glActiveTexture(GL_TEXTURE0); 161 texture.unbind(); 162 } 163 164 if(cullMode != CullMode.cullNone) 165 glDisable(GL_CULL_FACE); 166 167 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); 168 } 169 170 /// 171 void validate() 172 { 173 _program.validate(); 174 } 175 176 private: 177 GLProgram _program; 178 179 @Serialize 180 string _vshader; 181 @Serialize 182 string _fshader; 183 @Serialize 184 string _shaderName; 185 }