2 * Copyright (c) 2022 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
27 [[maybe_unused]] std::vector<std::string> split(const std::string& s, char seperator)
29 std::vector<std::string> output;
30 std::string::size_type prev_pos = 0, pos = 0;
31 while((pos = s.find(seperator, pos)) != std::string::npos)
33 std::string substring( s.substr(prev_pos, pos-prev_pos) );
34 output.push_back(substring);
37 output.push_back(s.substr(prev_pos, pos-prev_pos)); // Last word
41 int GetEnvInt(const char* name, int def)
43 auto v = getenv(name);
44 return v ? atoi(v) : def;
47 [[maybe_unused]] std::string GetEnvString(const char* name, std::string def = "")
49 auto v = getenv(name);
50 return v ? std::string(v) : def;
53 const uint32_t MAX_CUBES = GetEnvInt("MAX_CUBES", 200);
55 #define GL(x) {glGetError();{x;};auto err = glGetError();if(err){ \
56 printf("%p:%d: ERROR: 0x%X\n", this, __LINE__, int(err));} }
58 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};
60 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};
62 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};
64 constexpr float QUAD_VERTS[] = {
65 // positions // colors // texture coords
72 constexpr unsigned short QUAD_INDICES[] = {
77 constexpr float QUAD_UV[] = {
78 // positions // colors // texture coords
79 1.0f, 1.0f, // top right
80 1.0f, 0.0f, // bottom right
81 0.0f, 0.0f, // bottom left
82 0.0f, 1.0f // top left
85 float matrixDegreesToRadians(float degrees)
87 return M_PI * degrees / 180.0f;
90 [[maybe_unused]] void matrixIdentityFunction(float* matrix)
114 [[maybe_unused]] void matrixMultiply(float* destination, float* operand1, float* operand2)
118 for(i = 0; i < 4; i++)
120 for(j = 0; j < 4; j++)
122 theResult[4 * i + j] = operand1[j] * operand2[4 * i] + operand1[4 + j] * operand2[4 * i + 1] +
123 operand1[8 + j] * operand2[4 * i + 2] + operand1[12 + j] * operand2[4 * i + 3];
126 for(int i = 0; i < 16; i++)
128 destination[i] = theResult[i];
132 [[maybe_unused]] void matrixTranslate(float* matrix, float x, float y, float z)
134 float temporaryMatrix[16];
135 matrixIdentityFunction(temporaryMatrix);
136 temporaryMatrix[12] = x;
137 temporaryMatrix[13] = y;
138 temporaryMatrix[14] = z;
139 matrixMultiply(matrix, temporaryMatrix, matrix);
142 [[maybe_unused]] void matrixScale(float* matrix, float x, float y, float z)
144 float tempMatrix[16];
145 matrixIdentityFunction(tempMatrix);
149 matrixMultiply(matrix, tempMatrix, matrix);
152 [[maybe_unused]] void matrixRotateX(float* matrix, float angle)
154 float tempMatrix[16];
155 matrixIdentityFunction(tempMatrix);
156 tempMatrix[5] = cos(matrixDegreesToRadians(angle));
157 tempMatrix[9] = -sin(matrixDegreesToRadians(angle));
158 tempMatrix[6] = sin(matrixDegreesToRadians(angle));
159 tempMatrix[10] = cos(matrixDegreesToRadians(angle));
160 matrixMultiply(matrix, tempMatrix, matrix);
162 [[maybe_unused]] void matrixRotateY(float* matrix, float angle)
164 float tempMatrix[16];
165 matrixIdentityFunction(tempMatrix);
166 tempMatrix[0] = cos(matrixDegreesToRadians(angle));
167 tempMatrix[8] = sin(matrixDegreesToRadians(angle));
168 tempMatrix[2] = -sin(matrixDegreesToRadians(angle));
169 tempMatrix[10] = cos(matrixDegreesToRadians(angle));
170 matrixMultiply(matrix, tempMatrix, matrix);
172 [[maybe_unused]] void matrixRotateZ(float* matrix, float angle)
174 float tempMatrix[16];
175 matrixIdentityFunction(tempMatrix);
176 tempMatrix[0] = cos(matrixDegreesToRadians(angle));
177 tempMatrix[4] = -sin(matrixDegreesToRadians(angle));
178 tempMatrix[1] = sin(matrixDegreesToRadians(angle));
179 tempMatrix[5] = cos(matrixDegreesToRadians(angle));
180 matrixMultiply(matrix, tempMatrix, matrix);
183 void matrixFrustum(float* matrix, float left, float right, float bottom, float top, float zNear, float zFar)
185 float temp, xDistance, yDistance, zDistance;
187 xDistance = right - left;
188 yDistance = top - bottom;
189 zDistance = zFar - zNear;
190 matrixIdentityFunction(matrix);
191 matrix[0] = temp / xDistance;
192 matrix[5] = temp / yDistance;
193 matrix[8] = (right + left) / xDistance;
194 matrix[9] = (top + bottom) / yDistance;
195 matrix[10] = (-zFar - zNear) / zDistance;
197 matrix[14] = (-temp * zFar) / zDistance;
201 [[maybe_unused]] void matrixPerspective(float* matrix, float fieldOfView, float aspectRatio, float zNear, float zFar)
204 ymax = zNear * tanf(fieldOfView * M_PI / 360.0);
205 xmax = ymax * aspectRatio;
206 matrixFrustum(matrix, -xmax, xmax, -ymax, ymax, zNear, zFar);
211 NativeRenderer::~NativeRenderer() = default;
213 NativeRenderer::NativeRenderer(const CreateInfo& info )
214 : mWidth(info.width),
215 mHeight(info.height),
220 void NativeRenderer::PrepareShader()
222 static const char glVertexShader[] =
223 "attribute vec4 vertexPosition;\n"
224 "attribute vec3 vertexColour;\n"
225 "varying vec3 fragColour;\n"
226 "uniform mat4 projection;\n"
227 "uniform mat4 modelView;\n"
230 " gl_Position = projection * modelView * vertexPosition;\n"
231 " fragColour = vertexColour;\n"
234 static const char glFragmentShader[] =
235 "precision mediump float;\n"
236 "varying vec3 fragColour;\n"
239 " gl_FragColor = vec4(fragColour, 1.0);\n"
242 mProgramId = CreateProgram(glVertexShader, glFragmentShader);
245 void NativeRenderer::Setup(int width, int height)
249 mVertexLocation = glGetAttribLocation(mProgramId, "vertexPosition");
250 mVertexColourLocation = glGetAttribLocation(mProgramId, "vertexColour");
251 mProjectionLocation = glGetUniformLocation(mProgramId, "projection");
252 mModelViewLocation = glGetUniformLocation(mProgramId, "modelView");
254 GL(glEnable(GL_DEPTH_TEST));
257 GLuint NativeRenderer::CreateProgram(const char* vertexSource, const char* fragmentSource)
259 GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, vertexSource);
264 GLuint fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fragmentSource);
269 GLuint program = glCreateProgram();
272 GL(glAttachShader(program, vertexShader));
273 GL(glAttachShader(program, fragmentShader));
274 GL(glLinkProgram(program));
275 GLint linkStatus = GL_FALSE;
276 GL(glGetProgramiv(program, GL_LINK_STATUS, &linkStatus));
277 if(linkStatus != GL_TRUE)
280 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
283 char* buf = (char*)malloc(bufLength);
286 glGetProgramInfoLog(program, bufLength, NULL, buf);
290 glDeleteProgram(program);
297 GLuint NativeRenderer::LoadShader(GLenum shaderType, const char* shaderSource)
299 GLuint shader = glCreateShader(shaderType);
302 GL(glShaderSource(shader, 1, &shaderSource, NULL));
303 GL(glCompileShader(shader));
305 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
306 if(compiled != GL_TRUE)
309 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
313 char* logBuffer = (char*)malloc(infoLen);
315 if(logBuffer != NULL)
317 glGetShaderInfoLog(shader, infoLen, NULL, logBuffer);
322 glDeleteShader(shader);
331 void NativeRenderer::RenderCube(const Dali::RenderCallbackInput& input)
333 uint32_t drawCount = 0;
335 float& angle = mAngle;
337 [[maybe_unused]] auto x = mCreateInfo.viewportX; // float(mWidth - input.size.width) * 0.5f;
338 [[maybe_unused]] auto y = mCreateInfo.viewportY; // float(mHeight - input.size.height) * 0.5f;
339 auto w = mCreateInfo.width;
340 auto h = mCreateInfo.height;
342 matrixPerspective(mProjectionMatrix, 45, (float)w / (float)h, 0.1f, 100);
344 GL(glViewport(x, y, w, h));
345 GL(glEnable(GL_DEPTH_TEST));
346 if(!mCreateInfo.offscreen)
348 GL(glEnable(GL_SCISSOR_TEST));
349 GL(glScissor(x, y, w, h));
353 GL(glDisable(GL_SCISSOR_TEST));
355 GL(glClearColor(mCreateInfo.clearColor[0],
356 mCreateInfo.clearColor[1],
357 mCreateInfo.clearColor[2],
358 mCreateInfo.clearColor[3]
361 GL(glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT));
363 GL(glUseProgram(mProgramId));
364 GL(glVertexAttribPointer(mVertexLocation, 3, GL_FLOAT, GL_FALSE, 0, CUBE_VERTICES));
365 GL(glEnableVertexAttribArray(mVertexLocation));
366 GL(glVertexAttribPointer(mVertexColourLocation, 3, GL_FLOAT, GL_FALSE, 0, CUBE_COLOURS));
367 GL(glEnableVertexAttribArray(mVertexColourLocation));
371 const auto maxCubes = int(MAX_CUBES);
373 for( int i = 0; i < int(maxCubes); ++i)
375 GL(matrixIdentityFunction(mModelViewMatrix));
376 matrixScale(mModelViewMatrix, 0.2f, 0.2f, 0.2f);
377 matrixRotateX(mModelViewMatrix, angle);
378 matrixRotateY(mModelViewMatrix, angle);
380 if(mPosX.size() == uint32_t(i))
382 auto x = float((rand() % max) - (max / 2)) / 1000.0f;
383 auto y = float((rand() % max) - (max / 2)) / 1000.0f;
384 mPosX.emplace_back(x);
385 mPosY.emplace_back(y);
387 matrixTranslate(mModelViewMatrix, mPosX[i], mPosY[i], -5.0f);
388 GL(glUniformMatrix4fv(mProjectionLocation, 1, GL_FALSE, mProjectionMatrix));
389 GL(glUniformMatrix4fv(mModelViewLocation, 1, GL_FALSE, mModelViewMatrix));
390 GL(glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, CUBE_INDICES));
400 void NativeRenderer::GlViewInitCallback(const Dali::RenderCallbackInput& input)
402 Setup(mWidth, mHeight);
403 mState = State::RENDER;
406 int NativeRenderer::GlViewRenderCallback(const Dali::RenderCallbackInput& input)
412 void NativeRenderer::GlViewTerminateCallback(const Dali::RenderCallbackInput& input)
414 // Nothing to do here