1 /* 2 Copyright (c) 2017-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.material; 29 30 import std.math; 31 import std.algorithm; 32 import dlib.core.memory; 33 import dlib.math.vector; 34 import dlib.image.color; 35 import dlib.container.dict; 36 import derelict.opengl; 37 import dagon.core.ownership; 38 import dagon.graphics.texture; 39 import dagon.graphics.rc; 40 41 enum 42 { 43 CBlack = Color4f(0.0f, 0.0f, 0.0f, 1.0f), 44 CWhite = Color4f(1.0f, 1.0f, 1.0f, 1.0f), 45 CRed = Color4f(1.0f, 0.0f, 0.0f, 1.0f), 46 COrange = Color4f(1.0f, 0.5f, 0.0f, 1.0f), 47 CYellow = Color4f(1.0f, 1.0f, 0.0f, 1.0f), 48 CGreen = Color4f(0.0f, 1.0f, 0.0f, 1.0f), 49 CCyan = Color4f(0.0f, 1.0f, 1.0f, 1.0f), 50 CBlue = Color4f(0.0f, 0.0f, 1.0f, 1.0f), 51 CPurple = Color4f(0.5f, 0.0f, 1.0f, 1.0f), 52 CMagenta = Color4f(1.0f, 0.0f, 1.0f, 1.0f) 53 } 54 55 enum MaterialInputType 56 { 57 Undefined, 58 Bool, 59 Integer, 60 Float, 61 Vec2, 62 Vec3, 63 Vec4 64 } 65 66 struct MaterialInput 67 { 68 MaterialInputType type; 69 union 70 { 71 bool asBool; 72 int asInteger; 73 float asFloat; 74 Vector2f asVector2f; 75 Vector3f asVector3f; 76 Vector4f asVector4f; 77 } 78 Texture texture; 79 80 float getNumericValue() 81 { 82 float res; 83 if (type == MaterialInputType.Bool || 84 type == MaterialInputType.Integer) 85 { 86 res = asInteger; 87 } 88 else if (type == MaterialInputType.Float) 89 { 90 res = asFloat; 91 } 92 return res; 93 } 94 95 Color4f sample(float u, float v) 96 { 97 if (texture !is null) 98 { 99 int x = cast(int)floor(u * texture.width); 100 int y = cast(int)floor(v * texture.height); 101 return texture.image[x, y]; 102 } 103 else if (type == MaterialInputType.Vec4) 104 return Color4f(asVector4f); 105 else if (type == MaterialInputType.Vec3) 106 return Color4f(asVector3f.x, asVector3f.y, asVector3f.z, 1.0f); 107 else if (type == MaterialInputType.Vec2) 108 return Color4f(asVector2f.x, asVector2f.y, 1.0f, 1.0f); 109 else if (type == MaterialInputType.Float) 110 return Color4f(asFloat, 1.0f, 1.0f, 1.0f); 111 else if (type == MaterialInputType.Bool || 112 type == MaterialInputType.Integer) 113 return Color4f(cast(float)asInteger, 1.0f, 1.0f, 1.0f); 114 else 115 return Color4f(0.0f, 0.0f, 0.0f, 0.0f); 116 } 117 } 118 119 MaterialInput materialInput(float v) 120 { 121 MaterialInput mi; 122 mi.asFloat = v; 123 mi.type = MaterialInputType.Float; 124 return mi; 125 } 126 127 abstract class Material: Owner 128 { 129 Dict!(MaterialInput, string) inputs; 130 131 this(Owner o) 132 { 133 super(o); 134 135 inputs = New!(Dict!(MaterialInput, string)); 136 } 137 138 ~this() 139 { 140 Delete(inputs); 141 } 142 143 final void opDispatch(string name, T)(T value) @property 144 { 145 setInput(name, value); 146 } 147 148 final MaterialInput* setInput(T)(string name, T value) 149 { 150 MaterialInput input; 151 static if (is(T == bool)) 152 { 153 input.type = MaterialInputType.Bool; 154 input.asBool = value; 155 } 156 else static if (is(T == int)) 157 { 158 input.type = MaterialInputType.Integer; 159 input.asInteger = value; 160 } 161 else static if (is(T == float) || is(T == double)) 162 { 163 input.type = MaterialInputType.Float; 164 input.asFloat = value; 165 } 166 else static if (is(T == Vector2f)) 167 { 168 input.type = MaterialInputType.Vec2; 169 input.asVector2f = value; 170 } 171 else static if (is(T == Vector3f)) 172 { 173 input.type = MaterialInputType.Vec3; 174 input.asVector3f = value; 175 } 176 else static if (is(T == Vector4f)) 177 { 178 input.type = MaterialInputType.Vec4; 179 input.asVector4f = value; 180 } 181 else static if (is(T == Color4f)) 182 { 183 input.type = MaterialInputType.Vec4; 184 input.asVector4f = value; 185 } 186 else static if (is(T == Texture)) 187 { 188 input.texture = value; 189 if (value.format == GL_RED) 190 input.type = MaterialInputType.Float; 191 else if (value.format == GL_RG) 192 input.type = MaterialInputType.Vec2; 193 else if (value.format == GL_RGB) 194 input.type = MaterialInputType.Vec3; 195 else if (value.format == GL_RGBA) 196 input.type = MaterialInputType.Vec4; 197 } 198 else 199 { 200 input.type = MaterialInputType.Undefined; 201 } 202 203 inputs[name] = input; 204 return (name in inputs); 205 } 206 207 void bind(RenderingContext* rc); 208 void unbind(RenderingContext* rc); 209 } 210