2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "native-renderer.h"
22 * Set of math helper functions
26 [[maybe_unused]] std::vector<std::string> split(const std::string& s, char seperator)
28 std::vector<std::string> output;
29 std::string::size_type prev_pos = 0, pos = 0;
30 while((pos = s.find(seperator, pos)) != std::string::npos)
32 std::string substring(s.substr(prev_pos, pos - prev_pos));
33 output.push_back(substring);
36 output.push_back(s.substr(prev_pos, pos - prev_pos)); // Last word
40 int GetEnvInt(const char* name, int def)
42 auto v = getenv(name);
43 return v ? atoi(v) : def;
46 [[maybe_unused]] std::string GetEnvString(const char* name, std::string def = "")
48 auto v = getenv(name);
49 return v ? std::string(v) : def;
52 const uint32_t MAX_CUBES = GetEnvInt("MAX_CUBES", 200);
60 auto err = glGetError(); \
63 printf("%p:%d: ERROR: 0x%X\n", this, __LINE__, int(err)); \
67 constexpr GLfloat CUBE_VERTICES[] = {-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f};
69 constexpr GLfloat CUBE_COLOURS[] = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
71 constexpr GLushort CUBE_INDICES[] = {0, 2, 3, 0, 1, 3, 4, 6, 7, 4, 5, 7, 8, 9, 10, 11, 8, 10, 12, 13, 14, 15, 12, 14, 16, 17, 18, 16, 19, 18, 20, 21, 22, 20, 23, 22};
73 constexpr float QUAD_VERTS[] = {
74 // positions // colors // texture coords
85 constexpr unsigned short QUAD_INDICES[] = {
88 constexpr float QUAD_UV[] = {
89 // positions // colors // texture coords
100 float matrixDegreesToRadians(float degrees)
102 return M_PI * degrees / 180.0f;
105 [[maybe_unused]] void matrixIdentityFunction(float* matrix)
129 [[maybe_unused]] void matrixMultiply(float* destination, float* operand1, float* operand2)
133 for(i = 0; i < 4; i++)
135 for(j = 0; j < 4; j++)
137 theResult[4 * i + j] = operand1[j] * operand2[4 * i] + operand1[4 + j] * operand2[4 * i + 1] +
138 operand1[8 + j] * operand2[4 * i + 2] + operand1[12 + j] * operand2[4 * i + 3];
141 for(i = 0; i < 16; i++)
143 destination[i] = theResult[i];
147 [[maybe_unused]] void matrixTranslate(float* matrix, float x, float y, float z)
149 float temporaryMatrix[16];
150 matrixIdentityFunction(temporaryMatrix);
151 temporaryMatrix[12] = x;
152 temporaryMatrix[13] = y;
153 temporaryMatrix[14] = z;
154 matrixMultiply(matrix, temporaryMatrix, matrix);
157 [[maybe_unused]] void matrixScale(float* matrix, float x, float y, float z)
159 float tempMatrix[16];
160 matrixIdentityFunction(tempMatrix);
164 matrixMultiply(matrix, tempMatrix, matrix);
167 [[maybe_unused]] void matrixRotateX(float* matrix, float angle)
169 float tempMatrix[16];
170 matrixIdentityFunction(tempMatrix);
171 tempMatrix[5] = cos(matrixDegreesToRadians(angle));
172 tempMatrix[9] = -sin(matrixDegreesToRadians(angle));
173 tempMatrix[6] = sin(matrixDegreesToRadians(angle));
174 tempMatrix[10] = cos(matrixDegreesToRadians(angle));
175 matrixMultiply(matrix, tempMatrix, matrix);
177 [[maybe_unused]] void matrixRotateY(float* matrix, float angle)
179 float tempMatrix[16];
180 matrixIdentityFunction(tempMatrix);
181 tempMatrix[0] = cos(matrixDegreesToRadians(angle));
182 tempMatrix[8] = sin(matrixDegreesToRadians(angle));
183 tempMatrix[2] = -sin(matrixDegreesToRadians(angle));
184 tempMatrix[10] = cos(matrixDegreesToRadians(angle));
185 matrixMultiply(matrix, tempMatrix, matrix);
187 [[maybe_unused]] void matrixRotateZ(float* matrix, float angle)
189 float tempMatrix[16];
190 matrixIdentityFunction(tempMatrix);
191 tempMatrix[0] = cos(matrixDegreesToRadians(angle));
192 tempMatrix[4] = -sin(matrixDegreesToRadians(angle));
193 tempMatrix[1] = sin(matrixDegreesToRadians(angle));
194 tempMatrix[5] = cos(matrixDegreesToRadians(angle));
195 matrixMultiply(matrix, tempMatrix, matrix);
198 void matrixFrustum(float* matrix, float left, float right, float bottom, float top, float zNear, float zFar)
200 float temp, xDistance, yDistance, zDistance;
202 xDistance = right - left;
203 yDistance = top - bottom;
204 zDistance = zFar - zNear;
205 matrixIdentityFunction(matrix);
206 matrix[0] = temp / xDistance;
207 matrix[5] = temp / yDistance;
208 matrix[8] = (right + left) / xDistance;
209 matrix[9] = (top + bottom) / yDistance;
210 matrix[10] = (-zFar - zNear) / zDistance;
212 matrix[14] = (-temp * zFar) / zDistance;
216 [[maybe_unused]] void matrixPerspective(float* matrix, float fieldOfView, float aspectRatio, float zNear, float zFar)
219 ymax = zNear * tanf(fieldOfView * M_PI / 360.0);
220 xmax = ymax * aspectRatio;
221 matrixFrustum(matrix, -xmax, xmax, -ymax, ymax, zNear, zFar);
226 NativeRenderer::~NativeRenderer() = default;
228 NativeRenderer::NativeRenderer(const CreateInfo& info)
229 : mWidth(info.width),
230 mHeight(info.height),
235 void NativeRenderer::PrepareShader()
237 static const char glVertexShader[] =
238 "attribute vec4 vertexPosition;\n"
239 "attribute vec3 vertexColour;\n"
240 "varying vec3 fragColour;\n"
241 "uniform mat4 projection;\n"
242 "uniform mat4 modelView;\n"
245 " gl_Position = projection * modelView * vertexPosition;\n"
246 " fragColour = vertexColour;\n"
249 static const char glFragmentShader[] =
250 "precision mediump float;\n"
251 "varying vec3 fragColour;\n"
254 " gl_FragColor = vec4(fragColour, 1.0);\n"
257 mProgramId = CreateProgram(glVertexShader, glFragmentShader);
260 void NativeRenderer::Setup(int width, int height)
264 mVertexLocation = glGetAttribLocation(mProgramId, "vertexPosition");
265 mVertexColourLocation = glGetAttribLocation(mProgramId, "vertexColour");
266 mProjectionLocation = glGetUniformLocation(mProgramId, "projection");
267 mModelViewLocation = glGetUniformLocation(mProgramId, "modelView");
269 GL(glEnable(GL_DEPTH_TEST));
272 GLuint NativeRenderer::CreateProgram(const char* vertexSource, const char* fragmentSource)
274 GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, vertexSource);
279 GLuint fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fragmentSource);
284 GLuint program = glCreateProgram();
287 GL(glAttachShader(program, vertexShader));
288 GL(glAttachShader(program, fragmentShader));
289 GL(glLinkProgram(program));
290 GLint linkStatus = GL_FALSE;
291 GL(glGetProgramiv(program, GL_LINK_STATUS, &linkStatus));
292 if(linkStatus != GL_TRUE)
295 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
298 char* buf = (char*)malloc(bufLength);
301 glGetProgramInfoLog(program, bufLength, NULL, buf);
305 glDeleteProgram(program);
312 GLuint NativeRenderer::LoadShader(GLenum shaderType, const char* shaderSource)
314 GLuint shader = glCreateShader(shaderType);
317 GL(glShaderSource(shader, 1, &shaderSource, NULL));
318 GL(glCompileShader(shader));
320 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
321 if(compiled != GL_TRUE)
324 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
328 char* logBuffer = (char*)malloc(infoLen);
330 if(logBuffer != NULL)
332 glGetShaderInfoLog(shader, infoLen, NULL, logBuffer);
337 glDeleteShader(shader);
346 void NativeRenderer::RenderCube(const Dali::RenderCallbackInput& input)
348 uint32_t drawCount = 0;
350 float& angle = mAngle;
352 [[maybe_unused]] auto x = mCreateInfo.viewportX; // float(mWidth - input.size.width) * 0.5f;
353 [[maybe_unused]] auto y = mCreateInfo.viewportY; // float(mHeight - input.size.height) * 0.5f;
354 auto w = mCreateInfo.width;
355 auto h = mCreateInfo.height;
357 matrixPerspective(mProjectionMatrix, 45, (float)w / (float)h, 0.1f, 100);
359 GL(glViewport(x, y, w, h));
360 GL(glEnable(GL_DEPTH_TEST));
361 if(!mCreateInfo.offscreen)
363 GL(glEnable(GL_SCISSOR_TEST));
364 GL(glScissor(x, y, w, h));
368 GL(glDisable(GL_SCISSOR_TEST));
370 GL(glClearColor(mCreateInfo.clearColor[0],
371 mCreateInfo.clearColor[1],
372 mCreateInfo.clearColor[2],
373 mCreateInfo.clearColor[3]));
375 GL(glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT));
377 GL(glUseProgram(mProgramId));
378 GL(glVertexAttribPointer(mVertexLocation, 3, GL_FLOAT, GL_FALSE, 0, CUBE_VERTICES));
379 GL(glEnableVertexAttribArray(mVertexLocation));
380 GL(glVertexAttribPointer(mVertexColourLocation, 3, GL_FLOAT, GL_FALSE, 0, CUBE_COLOURS));
381 GL(glEnableVertexAttribArray(mVertexColourLocation));
385 const auto maxCubes = int(MAX_CUBES);
387 for(int i = 0; i < int(maxCubes); ++i)
389 GL(matrixIdentityFunction(mModelViewMatrix));
390 matrixScale(mModelViewMatrix, 0.2f, 0.2f, 0.2f);
391 matrixRotateX(mModelViewMatrix, angle);
392 matrixRotateY(mModelViewMatrix, angle);
394 if(mPosX.size() == uint32_t(i))
396 auto xPos = float((rand() % max) - (max / 2)) / 1000.0f;
397 auto yPos = float((rand() % max) - (max / 2)) / 1000.0f;
398 mPosX.emplace_back(xPos);
399 mPosY.emplace_back(yPos);
401 matrixTranslate(mModelViewMatrix, mPosX[i], mPosY[i], -5.0f);
402 GL(glUniformMatrix4fv(mProjectionLocation, 1, GL_FALSE, mProjectionMatrix));
403 GL(glUniformMatrix4fv(mModelViewLocation, 1, GL_FALSE, mModelViewMatrix));
404 GL(glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, CUBE_INDICES));
414 void NativeRenderer::GlViewInitCallback(const Dali::RenderCallbackInput& input)
416 Setup(mWidth, mHeight);
417 mState = State::RENDER;
420 int NativeRenderer::GlViewRenderCallback(const Dali::RenderCallbackInput& input)
426 void NativeRenderer::GlViewTerminateCallback(const Dali::RenderCallbackInput& input)
428 // Nothing to do here