paintershaderprogram.cpp

main 227 lines · 6.6 KB Raw
Alex Alex Commit Client Upload Part 2 19/10/2026 00:06
1/*
2 * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "paintershaderprogram.h"
24#include "graphics.h"
25#include "painter.h"
26#include "texture.h"
27#include "texturemanager.h"
28#include <framework/core/clock.h>
29#include <framework/platform/platformwindow.h>
30
31PainterShaderProgram::PainterShaderProgram(const std::string &name)
32 : ShaderProgram(name) {
33 m_startTime = g_clock.seconds();
34 m_depth = 0;
35 m_color = Color::white;
36 m_time = 0;
37}
38
39void PainterShaderProgram::setupUniforms() {
40 bindUniformLocation(TRANSFORM_MATRIX_UNIFORM, "u_TransformMatrix");
41 bindUniformLocation(PROJECTION_MATRIX_UNIFORM, "u_ProjectionMatrix");
42 bindUniformLocation(TEXTURE_MATRIX_UNIFORM, "u_TextureMatrix");
43
44 bindUniformLocation(COLOR_UNIFORM, "u_Color");
45 bindUniformLocation(DEPTH_UNIFORM, "u_Depth");
46 bindUniformLocation(TIME_UNIFORM, "u_Time");
47
48 bindUniformLocation(TEX0_UNIFORM, "u_Tex0");
49 bindUniformLocation(TEX1_UNIFORM, "u_Tex1");
50 bindUniformLocation(TEX2_UNIFORM, "u_Tex2");
51 bindUniformLocation(TEX3_UNIFORM, "u_Tex3");
52
53 bindUniformLocation(ATLAS_TEX0_UNIFORM, "u_Atlas");
54 bindUniformLocation(ATLAS_TEX1_UNIFORM, "u_Fonts");
55
56 bindUniformLocation(RESOLUTION_UNIFORM, "u_Resolution");
57 bindUniformLocation(OFFSET_UNIFORM, "u_Offset");
58 bindUniformLocation(CENTER_UNIFORM, "u_Center");
59
60 // VALUES
61 setUniformValue(TRANSFORM_MATRIX_UNIFORM, m_transformMatrix);
62 setUniformValue(PROJECTION_MATRIX_UNIFORM, m_projectionMatrix);
63 setUniformValue(TEXTURE_MATRIX_UNIFORM, m_textureMatrix);
64
65 if (!m_useColorMatrix) {
66 setUniformValue(COLOR_UNIFORM, m_color);
67 }
68 setUniformValue(TIME_UNIFORM, m_time);
69 setUniformValue(DEPTH_UNIFORM, m_depth);
70
71 setUniformValue(TEX0_UNIFORM, 0);
72 setUniformValue(TEX1_UNIFORM, 1);
73 setUniformValue(TEX2_UNIFORM, 2);
74 setUniformValue(TEX3_UNIFORM, 3);
75
76 setUniformValue(ATLAS_TEX0_UNIFORM, 6);
77 setUniformValue(ATLAS_TEX1_UNIFORM, 7);
78
79 setUniformValue(RESOLUTION_UNIFORM, (float)m_resolution.width(),
80 (float)m_resolution.height());
81 setUniformValue(OFFSET_UNIFORM, (float)m_offset.x, (float)m_offset.y);
82 setUniformValue(CENTER_UNIFORM, (float)m_center.x, (float)m_center.y);
83}
84
85bool PainterShaderProgram::link() {
86 m_startTime = g_clock.seconds();
87 bindAttributeLocation(VERTEX_ATTR, "a_Vertex");
88 bindAttributeLocation(TEXCOORD_ATTR, "a_TexCoord");
89 bindAttributeLocation(DEPTH_ATTR, "a_Depth");
90 bindAttributeLocation(COLOR_ATTR, "a_Color");
91 bindAttributeLocation(DEPTH_TEXCOORD_ATTR, "a_DepthTexCoord");
92 if (!ShaderProgram::link())
93 return false;
94 bind();
95 setupUniforms();
96 release();
97 g_graphics.checkForError(stdext::format("%s (%s)", __FUNCTION__, getName()),
98 __FILE__, __LINE__);
99 return true;
100}
101
102void PainterShaderProgram::setTransformMatrix(const Matrix3 &transformMatrix) {
103 if (transformMatrix == m_transformMatrix)
104 return;
105
106 bind();
107 setUniformValue(TRANSFORM_MATRIX_UNIFORM, transformMatrix);
108 m_transformMatrix = transformMatrix;
109}
110
111void PainterShaderProgram::setProjectionMatrix(
112 const Matrix3 &projectionMatrix) {
113 if (projectionMatrix == m_projectionMatrix)
114 return;
115
116 bind();
117 setUniformValue(PROJECTION_MATRIX_UNIFORM, projectionMatrix);
118 m_projectionMatrix = projectionMatrix;
119}
120
121void PainterShaderProgram::setTextureMatrix(const Matrix3 &textureMatrix) {
122 if (textureMatrix == m_textureMatrix)
123 return;
124
125 bind();
126 setUniformValue(TEXTURE_MATRIX_UNIFORM, textureMatrix);
127 m_textureMatrix = textureMatrix;
128}
129
130void PainterShaderProgram::setColor(const Color &color) {
131 if (color == m_color || m_useColorMatrix)
132 return;
133
134 bind();
135 setUniformValue(COLOR_UNIFORM, color);
136 m_color = color;
137}
138
139void PainterShaderProgram::setMatrixColor(const Matrix4 &colors) {
140 bind();
141 setUniformValue(COLOR_UNIFORM, colors);
142}
143
144#ifdef WITH_DEPTH_BUFFER
145void PainterShaderProgram::setDepth(float depth) {
146 if (depth < 0.)
147 depth = 0.;
148
149 if (m_depth == depth)
150 return;
151
152 bind();
153 setUniformValue(DEPTH_UNIFORM, depth);
154 m_depth = depth;
155}
156#endif
157
158void PainterShaderProgram::setResolution(const Size &resolution) {
159 if (m_resolution == resolution)
160 return;
161
162 bind();
163 setUniformValue(RESOLUTION_UNIFORM, (float)resolution.width(),
164 (float)resolution.height());
165 m_resolution = resolution;
166}
167
168void PainterShaderProgram::setOffset(const Point &offset) {
169 if (m_offset == offset)
170 return;
171
172 bind();
173 m_offset = offset;
174 setUniformValue(OFFSET_UNIFORM, (float)m_offset.x, (float)m_offset.y);
175}
176
177void PainterShaderProgram::setCenter(const Point &center) {
178 if (m_center == center)
179 return;
180
181 bind();
182 m_center = center;
183 setUniformValue(CENTER_UNIFORM, (float)m_center.x, (float)m_center.y);
184}
185
186void PainterShaderProgram::updateTime() {
187 float time = g_clock.seconds() - m_startTime;
188 if (m_time == time)
189 return;
190
191 bind();
192 setUniformValue(TIME_UNIFORM, time);
193 m_time = time;
194}
195
196void PainterShaderProgram::addMultiTexture(const std::string &file) {
197 if (m_multiTextures.size() > 3)
198 g_logger.error(stdext::format(
199 "cannot add more multi textures to shader, the max is 3 - %s",
200 getName()));
201
202 TexturePtr texture = g_textures.getTexture(file);
203 if (!texture)
204 return;
205
206 texture->setSmooth(true);
207 texture->setRepeat(true);
208
209 m_multiTextures.push_back(texture);
210}
211
212void PainterShaderProgram::bindMultiTextures() {
213 if (m_multiTextures.size() == 0)
214 return;
215
216 int i = 1;
217 for (const TexturePtr &tex : m_multiTextures) {
218 tex->update();
219 glActiveTexture(GL_TEXTURE0 + i++);
220 glBindTexture(GL_TEXTURE_2D, tex->getId());
221 }
222
223 glActiveTexture(GL_TEXTURE0);
224}
225
226void PainterShaderProgram::clearMultiTextures() { m_multiTextures.clear(); }
227
Top