28 static const char* vertexShaderSource = R"( |
28 static const char* vertexShaderSource = R"( |
29 #version 330 core |
29 #version 330 core |
30 |
30 |
31 layout(location=0) in vec3 position; |
31 layout(location=0) in vec3 position; |
32 layout(location=1) in vec4 color; |
32 layout(location=1) in vec4 color; |
|
33 layout(location=2) in vec3 normal; |
33 out vec4 vColor; |
34 out vec4 vColor; |
34 uniform mat4 CameraTransformation; |
35 out vec3 vFragPos; |
|
36 out vec3 vNormal; |
|
37 uniform mat4 modelMatrix; |
|
38 uniform mat4 viewMatrix; |
|
39 uniform mat4 projectionMatrix; |
35 |
40 |
36 void main() |
41 void main() |
37 { |
42 { |
|
43 mat3 normalMatrix = transpose(inverse(mat3(modelMatrix))); |
|
44 vNormal = normalize(normalMatrix * normal); |
38 vColor = color; |
45 vColor = color; |
39 gl_Position = CameraTransformation * vec4(position, 1.0); |
46 vFragPos = vec3(modelMatrix * vec4(position, 1.0)); |
|
47 gl_Position = projectionMatrix * viewMatrix * vec4(vFragPos, 1.0); |
40 } |
48 } |
41 )"; |
49 )"; |
42 |
50 |
43 static const char* fragmentShaderSource = R"( |
51 static const char* fragmentShaderSource = R"( |
44 #version 330 core |
52 #version 330 core |
45 |
53 |
46 in vec4 vColor; |
54 in vec4 vColor; |
|
55 in vec3 vFragPos; |
|
56 in vec3 vNormal; |
47 out vec4 fColor; |
57 out vec4 fColor; |
|
58 const vec3 lightPos = vec3(0.5, 0.5, 0.5); |
|
59 const vec4 lightColor = vec4(1.0, 1.0, 1.0, 1.0); |
|
60 const float ambientStrength = 0.7; |
48 |
61 |
49 void main() |
62 void main() |
50 { |
63 { |
51 fColor = vColor; |
64 vec4 ambient = ambientStrength * lightColor; |
|
65 vec3 lightDirection = normalize(lightPos - vFragPos); |
|
66 vec4 diffuse = max(dot(vNormal, lightDirection), 0.0) * lightColor; |
|
67 fColor = (ambient + diffuse) * vColor; |
52 } |
68 } |
53 )"; |
69 )"; |
54 |
70 |
55 gl::Compiler::Compiler(const ColorTable& colorTable, QObject* parent) : |
71 gl::Compiler::Compiler(const ColorTable& colorTable, QObject* parent) : |
56 QObject{parent}, |
72 QObject{parent}, |
95 object.buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw); |
111 object.buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw); |
96 object.vertexArray.create(); |
112 object.vertexArray.create(); |
97 object.vertexArray.bind(); |
113 object.vertexArray.bind(); |
98 object.program->enableAttributeArray(0); |
114 object.program->enableAttributeArray(0); |
99 object.program->enableAttributeArray(1); |
115 object.program->enableAttributeArray(1); |
100 constexpr int stride = 7 * sizeof(GLfloat); |
116 object.program->enableAttributeArray(2); |
101 object.program->setAttributeBuffer(0, GL_FLOAT, 0 * sizeof(GLfloat), 3, stride); |
117 constexpr int stride = sizeof(gl::Vertex); |
102 object.program->setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(GLfloat), 4, stride); |
118 object.program->setAttributeBuffer(0, GL_FLOAT, offsetof(gl::Vertex, position), 3, stride); |
|
119 object.program->setAttributeBuffer(1, GL_FLOAT, offsetof(gl::Vertex, color), 4, stride); |
|
120 object.program->setAttributeBuffer(2, GL_FLOAT, offsetof(gl::Vertex, normal), 3, stride); |
103 object.vertexArray.release(); |
121 object.vertexArray.release(); |
104 object.buffer.release(); |
122 object.buffer.release(); |
105 object.program->release(); |
123 object.program->release(); |
106 } |
124 } |
107 this->initialized = true; |
125 this->initialized = true; |
109 } |
127 } |
110 |
128 |
111 void gl::Compiler::build(Model* model, DocumentManager* context) |
129 void gl::Compiler::build(Model* model, DocumentManager* context) |
112 { |
130 { |
113 this->boundingBox = {}; |
131 this->boundingBox = {}; |
114 std::vector<GLfloat> vboData[gl::NUM_ARRAY_CLASSES]; |
132 std::vector<gl::Vertex> vboData[gl::NUM_ARRAY_CLASSES]; |
115 const std::vector<gl::Polygon> polygons = model->getPolygons(context); |
133 const std::vector<gl::Polygon> polygons = model->getPolygons(context); |
116 for (const gl::Polygon& polygon : polygons) |
134 for (const gl::Polygon& polygon : polygons) |
117 { |
135 { |
118 this->buildPolygon(polygon, vboData); |
136 this->buildPolygon(polygon, vboData); |
119 } |
137 } |
120 for (int arrayId = 0; arrayId < gl::NUM_ARRAY_CLASSES; arrayId += 1) |
138 for (int arrayId = 0; arrayId < gl::NUM_ARRAY_CLASSES; arrayId += 1) |
121 { |
139 { |
122 auto& buffer = this->glObjects[arrayId].buffer; |
140 auto& buffer = this->glObjects[arrayId].buffer; |
123 auto& vector = vboData[arrayId]; |
141 auto& vector = vboData[arrayId]; |
124 this->storedVboSizes[arrayId] = vector.size(); |
142 this->storedVertexCounts[arrayId] = vector.size(); |
125 buffer.bind(); |
143 buffer.bind(); |
126 buffer.allocate(vector.data(), static_cast<int>(vector.size() * sizeof vector[0])); |
144 buffer.allocate(vector.data(), static_cast<int>(vector.size() * sizeof vector[0])); |
127 buffer.release(); |
145 buffer.release(); |
128 } |
146 } |
129 } |
147 } |
153 const int g = (id.value / 0x100) % 0x100; |
171 const int g = (id.value / 0x100) % 0x100; |
154 const int b = id.value % 0x100; |
172 const int b = id.value % 0x100; |
155 return {r, g, b}; |
173 return {r, g, b}; |
156 } |
174 } |
157 |
175 |
158 void gl::Compiler::buildPolygon(gl::Polygon polygon, std::vector<GLfloat>* vboData) |
176 void gl::Compiler::buildPolygon(gl::Polygon polygon, std::vector<gl::Vertex>* vboData) |
159 { |
177 { |
160 const gl::ArrayClass vboClass = classifyPolygon(polygon); |
178 const gl::ArrayClass vboClass = classifyPolygon(polygon); |
161 //std::vector<GLfloat>& vertexBuffer = vboData[gl::vboIndex({vboClass, gl::VboSubclass::VertexData})]; |
179 std::vector<gl::Vertex>& vertexBuffer = vboData[static_cast<int>(vboClass)]; |
162 std::vector<GLfloat>& vertexBuffer = vboData[static_cast<int>(vboClass)]; |
|
163 /* |
|
164 std::vector<GLfloat>& normalsBuffer = vboData[gl::vboIndex({vboClass, gl::VboSubclass::Normals})]; |
|
165 auto vertexRing = iter::ring(polygon.vertices, polygon.numPolygonVertices()); |
180 auto vertexRing = iter::ring(polygon.vertices, polygon.numPolygonVertices()); |
166 reserveMore(normalsBuffer, polygon.numPolygonVertices() * 3_z); |
181 reserveMore(vertexBuffer, polygon.numPolygonVertices()); |
|
182 const QColor color = this->getColorForPolygon(polygon); |
167 for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1) |
183 for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1) |
168 { |
184 { |
169 const glm::vec3& v1 = vertexRing[i - 1]; |
185 const glm::vec3& v1 = vertexRing[i - 1]; |
170 const glm::vec3& v2 = vertexRing[i]; |
186 const glm::vec3& v2 = vertexRing[i]; |
171 const glm::vec3& v3 = vertexRing[i + 1]; |
187 const glm::vec3& v3 = vertexRing[i + 1]; |
172 const QVector3D normal = QVector3D::crossProduct(v3 - v2, v1 - v2).normalized(); |
|
173 for (const GLfloat coord : {normal.x(), normal.y(), normal.z()}) |
|
174 normalsBuffer.push_back(coord); |
|
175 } |
|
176 */ |
|
177 reserveMore(vertexBuffer, polygon.numPolygonVertices() * 7); |
|
178 const QColor color = this->getColorForPolygon(polygon); |
|
179 // Transform vertices so that they're suitable for GL rendering |
|
180 for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1) |
|
181 { |
|
182 glm::vec3& point = polygon.vertices[i]; |
|
183 this->boundingBox.consider(polygon.vertices[i]); |
188 this->boundingBox.consider(polygon.vertices[i]); |
184 vertexBuffer.push_back(static_cast<GLfloat>(point.x)); |
189 gl::Vertex& vertex = vertexBuffer.emplace_back(); |
185 vertexBuffer.push_back(static_cast<GLfloat>(point.y)); |
190 vertex.position = polygon.vertices[i]; |
186 vertexBuffer.push_back(static_cast<GLfloat>(point.z)); |
191 vertex.normal = glm::normalize(glm::cross(v1 - v2, v3 - v2)); |
187 vertexBuffer.push_back(static_cast<GLfloat>(color.redF())); |
192 vertex.color = glm::vec4{color.redF(), color.greenF(), color.blueF(), color.alphaF()}; |
188 vertexBuffer.push_back(static_cast<GLfloat>(color.greenF())); |
|
189 vertexBuffer.push_back(static_cast<GLfloat>(color.blueF())); |
|
190 vertexBuffer.push_back(static_cast<GLfloat>(color.alphaF())); |
|
191 } |
193 } |
192 } |
194 } |
193 |
195 |
194 QColor gl::Compiler::getColorForPolygon(const gl::Polygon& polygon) |
196 QColor gl::Compiler::getColorForPolygon(const gl::Polygon& polygon) |
195 { |
197 { |
234 auto& object = this->glObjects[static_cast<int>(arrayClass)]; |
236 auto& object = this->glObjects[static_cast<int>(arrayClass)]; |
235 object.program->release(); |
237 object.program->release(); |
236 object.vertexArray.release(); |
238 object.vertexArray.release(); |
237 } |
239 } |
238 |
240 |
239 std::size_t gl::Compiler::vboSize(const gl::ArrayClass arrayClass) const |
241 std::size_t gl::Compiler::vertexCount(const gl::ArrayClass arrayClass) const |
240 { |
242 { |
241 return this->storedVboSizes[static_cast<int>(arrayClass)]; |
243 return this->storedVertexCounts[static_cast<int>(arrayClass)]; |
242 } |
244 } |
243 |
|
244 int gl::vboIndex(const VboAddress vboAddress) |
|
245 { |
|
246 return static_cast<std::uint8_t>(vboAddress.vboClass) * gl::numVboSubclasses |
|
247 + static_cast<std::uint8_t>(vboAddress.vboSubclass); |
|
248 } |
|
249 |
|
250 QMatrix4x4 gl::toQMatrix(const glm::mat4& matrix) |
|
251 { |
|
252 return { |
|
253 matrix[0][0], |
|
254 matrix[0][1], |
|
255 matrix[0][2], |
|
256 matrix[0][3], |
|
257 matrix[1][0], |
|
258 matrix[1][1], |
|
259 matrix[1][2], |
|
260 matrix[1][3], |
|
261 matrix[2][0], |
|
262 matrix[2][1], |
|
263 matrix[2][2], |
|
264 matrix[2][3], |
|
265 matrix[3][0], |
|
266 matrix[3][1], |
|
267 matrix[3][2], |
|
268 matrix[3][3], |
|
269 }; |
|
270 } |
|