1 | #include "glsl_shader_compiler.h" |
2 | |
3 | #include <base/system.h> |
4 | #include <engine/graphics.h> |
5 | |
6 | CGLSLCompiler::CGLSLCompiler(int OpenGLVersionMajor, int OpenGLVersionMinor, int OpenGLVersionPatch, bool IsOpenGLES, float TextureLODBias) |
7 | { |
8 | m_OpenGLVersionMajor = OpenGLVersionMajor; |
9 | m_OpenGLVersionMinor = OpenGLVersionMinor; |
10 | m_OpenGLVersionPatch = OpenGLVersionPatch; |
11 | |
12 | m_IsOpenGLES = IsOpenGLES; |
13 | |
14 | m_TextureLODBias = TextureLODBias; |
15 | |
16 | m_HasTextureArray = false; |
17 | m_TextureReplaceType = 0; |
18 | } |
19 | |
20 | void CGLSLCompiler::AddDefine(const std::string &DefineName, const std::string &DefineValue) |
21 | { |
22 | m_vDefines.emplace_back(args: DefineName, args: DefineValue); |
23 | } |
24 | |
25 | void CGLSLCompiler::AddDefine(const char *pDefineName, const char *pDefineValue) |
26 | { |
27 | AddDefine(DefineName: std::string(pDefineName), DefineValue: std::string(pDefineValue)); |
28 | } |
29 | |
30 | void CGLSLCompiler::ClearDefines() |
31 | { |
32 | m_vDefines.clear(); |
33 | } |
34 | |
35 | void CGLSLCompiler::ParseLine(std::string &Line, const char *pReadLine, EGLSLShaderCompilerType Type) |
36 | { |
37 | EBackendType BackendType = m_IsOpenGLES ? BACKEND_TYPE_OPENGL_ES : BACKEND_TYPE_OPENGL; |
38 | bool IsNewOpenGL = (BackendType == BACKEND_TYPE_OPENGL ? (m_OpenGLVersionMajor >= 4 || (m_OpenGLVersionMajor == 3 && m_OpenGLVersionMinor == 3)) : m_OpenGLVersionMajor >= 3); |
39 | if(!IsNewOpenGL) |
40 | { |
41 | const char *pBuff = pReadLine; |
42 | char aTmpStr[1024]; |
43 | size_t TmpStrSize = 0; |
44 | while(*pBuff) |
45 | { |
46 | while(*pBuff && str_isspace(c: *pBuff)) |
47 | { |
48 | Line.append(n: 1, c: *pBuff); |
49 | ++pBuff; |
50 | } |
51 | |
52 | while(*pBuff && !str_isspace(c: *pBuff) && *pBuff != '(' && *pBuff != '.') |
53 | { |
54 | aTmpStr[TmpStrSize++] = *pBuff; |
55 | ++pBuff; |
56 | } |
57 | |
58 | if(TmpStrSize > 0) |
59 | { |
60 | aTmpStr[TmpStrSize] = 0; |
61 | TmpStrSize = 0; |
62 | if(str_comp(a: aTmpStr, b: "layout" ) == 0) |
63 | { |
64 | //search for ' in' |
65 | while(*pBuff && (*pBuff != ' ' || (*(pBuff + 1) && *(pBuff + 1) != 'i') || *(pBuff + 2) != 'n')) |
66 | { |
67 | ++pBuff; |
68 | } |
69 | |
70 | if(*pBuff == ' ' && *(pBuff + 1) == 'i' && *(pBuff + 2) == 'n') |
71 | { |
72 | pBuff += 3; |
73 | Line.append(s: "attribute" ); |
74 | Line.append(s: pBuff); |
75 | return; |
76 | } |
77 | else |
78 | { |
79 | dbg_msg(sys: "shadercompiler" , fmt: "Fix shader for older OpenGL versions." ); |
80 | } |
81 | } |
82 | else if(str_comp(a: aTmpStr, b: "noperspective" ) == 0 || str_comp(a: aTmpStr, b: "smooth" ) == 0 || str_comp(a: aTmpStr, b: "flat" ) == 0) |
83 | { |
84 | //search for 'in' or 'out' |
85 | while(*pBuff && ((*pBuff != 'i' || *(pBuff + 1) != 'n') && (*pBuff != 'o' || (*(pBuff + 1) && *(pBuff + 1) != 'u') || *(pBuff + 2) != 't'))) |
86 | { |
87 | // append anything that is inbetween noperspective & in/out vars |
88 | Line.push_back(c: *pBuff); |
89 | ++pBuff; |
90 | } |
91 | |
92 | bool Found = false; |
93 | if(*pBuff) |
94 | { |
95 | if(*pBuff == 'i' && *(pBuff + 1) == 'n') |
96 | { |
97 | pBuff += 2; |
98 | Found = true; |
99 | } |
100 | else if(*pBuff == 'o' && *(pBuff + 1) == 'u' && *(pBuff + 2) == 't') |
101 | { |
102 | pBuff += 3; |
103 | Found = true; |
104 | } |
105 | } |
106 | |
107 | if(!Found) |
108 | { |
109 | dbg_msg(sys: "shadercompiler" , fmt: "Fix shader for older OpenGL versions." ); |
110 | } |
111 | |
112 | Line.append(s: "varying" ); |
113 | Line.append(s: pBuff); |
114 | return; |
115 | } |
116 | else if(str_comp(a: aTmpStr, b: "out" ) == 0 || str_comp(a: aTmpStr, b: "in" ) == 0) |
117 | { |
118 | if(Type == GLSL_SHADER_COMPILER_TYPE_FRAGMENT && str_comp(a: aTmpStr, b: "out" ) == 0) |
119 | return; |
120 | Line.append(s: "varying" ); |
121 | Line.append(s: pBuff); |
122 | return; |
123 | } |
124 | else if(str_comp(a: aTmpStr, b: "FragClr" ) == 0) |
125 | { |
126 | Line.append(s: "gl_FragColor" ); |
127 | Line.append(s: pBuff); |
128 | return; |
129 | } |
130 | else if(str_comp(a: aTmpStr, b: "texture" ) == 0) |
131 | { |
132 | if(m_TextureReplaceType == GLSL_COMPILER_TEXTURE_REPLACE_TYPE_2D) |
133 | Line.append(s: "texture2D" ); |
134 | else if(m_TextureReplaceType == GLSL_COMPILER_TEXTURE_REPLACE_TYPE_3D) |
135 | Line.append(s: "texture3D" ); |
136 | else if(m_TextureReplaceType == GLSL_COMPILER_TEXTURE_REPLACE_TYPE_2D_ARRAY) |
137 | Line.append(s: "texture2DArray" ); |
138 | std::string RestLine; |
139 | ParseLine(Line&: RestLine, pReadLine: pBuff, Type); |
140 | Line.append(str: RestLine); |
141 | return; |
142 | } |
143 | else |
144 | { |
145 | Line.append(s: aTmpStr); |
146 | } |
147 | } |
148 | |
149 | if(*pBuff) |
150 | { |
151 | Line.append(n: 1, c: *pBuff); |
152 | ++pBuff; |
153 | } |
154 | } |
155 | } |
156 | else |
157 | { |
158 | if(BackendType == BACKEND_TYPE_OPENGL_ES) |
159 | { |
160 | const char *pBuff = pReadLine; |
161 | char aTmpStr[1024]; |
162 | size_t TmpStrSize = 0; |
163 | while(*pBuff) |
164 | { |
165 | while(*pBuff && str_isspace(c: *pBuff)) |
166 | { |
167 | Line.append(n: 1, c: *pBuff); |
168 | ++pBuff; |
169 | } |
170 | |
171 | while(*pBuff && !str_isspace(c: *pBuff) && *pBuff != '(' && *pBuff != '.') |
172 | { |
173 | aTmpStr[TmpStrSize++] = *pBuff; |
174 | ++pBuff; |
175 | } |
176 | |
177 | if(TmpStrSize > 0) |
178 | { |
179 | aTmpStr[TmpStrSize] = 0; |
180 | TmpStrSize = 0; |
181 | |
182 | if(str_comp(a: aTmpStr, b: "noperspective" ) == 0) |
183 | { |
184 | Line.append(s: "smooth" ); |
185 | Line.append(s: pBuff); |
186 | return; |
187 | } |
188 | // since GLES doesn't support texture LOD bias as global state, use the shader function instead(since GLES 3.0 uses shaders only anyway) |
189 | else if(str_comp(a: aTmpStr, b: "texture" ) == 0) |
190 | { |
191 | Line.append(s: "texture" ); |
192 | // check opening and closing brackets to find the end |
193 | int CurBrackets = 1; |
194 | while(*pBuff && *pBuff != '(') |
195 | { |
196 | Line.append(n: 1, c: *pBuff); |
197 | |
198 | ++pBuff; |
199 | } |
200 | |
201 | if(*pBuff) |
202 | { |
203 | Line.append(n: 1, c: *pBuff); |
204 | ++pBuff; |
205 | } |
206 | |
207 | while(*pBuff) |
208 | { |
209 | if(*pBuff == '(') |
210 | ++CurBrackets; |
211 | if(*pBuff == ')') |
212 | --CurBrackets; |
213 | |
214 | if(CurBrackets == 0) |
215 | { |
216 | // found end |
217 | Line.append(str: std::string(", " ) + std::to_string(val: m_TextureLODBias) + ")" ); |
218 | ++pBuff; |
219 | break; |
220 | } |
221 | else |
222 | Line.append(n: 1, c: *pBuff); |
223 | ++pBuff; |
224 | } |
225 | |
226 | Line.append(s: pBuff); |
227 | |
228 | return; |
229 | } |
230 | else |
231 | { |
232 | Line.append(s: aTmpStr); |
233 | } |
234 | } |
235 | |
236 | if(*pBuff) |
237 | { |
238 | Line.append(n: 1, c: *pBuff); |
239 | ++pBuff; |
240 | } |
241 | } |
242 | } |
243 | else |
244 | Line = pReadLine; |
245 | } |
246 | } |
247 | |