Last active
February 28, 2019 21:10
-
-
Save BaronKiko/6a77f0b84802feb9b4e14ca8f40578fb to your computer and use it in GitHub Desktop.
SOIL2 error
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <switch.h> | |
#include <EGL/egl.h> // EGL library | |
#include <EGL/eglext.h> // EGL extensions | |
#include <glad/glad.h> // glad library (OpenGL loader) | |
// GLM headers | |
#define GLM_FORCE_PURE | |
#include <glm/vec3.hpp> | |
#include <glm/vec4.hpp> | |
#include <glm/mat4x4.hpp> | |
#include <glm/gtc/type_ptr.hpp> | |
#include <glm/gtc/matrix_transform.hpp> | |
#include "SOIL2.h" | |
#include "Top_png.h" | |
#include "Bottom_png.h" | |
#include "Left_png.h" | |
#include "Right_png.h" | |
#include "Front_png.h" | |
#include "Back_png.h" | |
constexpr auto TAU = glm::two_pi<float>(); | |
//----------------------------------------------------------------------------- | |
// nxlink support | |
//----------------------------------------------------------------------------- | |
#ifndef ENABLE_NXLINK | |
#define TRACE(fmt,...) ((void)0) | |
#else | |
#include <unistd.h> | |
#define TRACE(fmt,...) printf("%s: " fmt "\n", __PRETTY_FUNCTION__, ## __VA_ARGS__) | |
static int s_nxlinkSock = -1; | |
static void initNxLink() | |
{ | |
if (R_FAILED(socketInitializeDefault())) | |
return; | |
s_nxlinkSock = nxlinkStdio(); | |
if (s_nxlinkSock >= 0) | |
TRACE("printf output now goes to nxlink server"); | |
else | |
socketExit(); | |
} | |
static void deinitNxLink() | |
{ | |
if (s_nxlinkSock >= 0) | |
{ | |
close(s_nxlinkSock); | |
socketExit(); | |
s_nxlinkSock = -1; | |
} | |
} | |
extern "C" void userAppInit() | |
{ | |
initNxLink(); | |
} | |
extern "C" void userAppExit() | |
{ | |
deinitNxLink(); | |
} | |
#endif | |
//----------------------------------------------------------------------------- | |
// EGL initialization | |
//----------------------------------------------------------------------------- | |
static EGLDisplay s_display; | |
static EGLContext s_context; | |
static EGLSurface s_surface; | |
static bool initEgl() | |
{ | |
// Connect to the EGL default display | |
s_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); | |
if (!s_display) | |
{ | |
TRACE("Could not connect to display! error: %d", eglGetError()); | |
goto _fail0; | |
} | |
// Initialize the EGL display connection | |
eglInitialize(s_display, nullptr, nullptr); | |
// Select OpenGL (Core) as the desired graphics API | |
if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) | |
{ | |
TRACE("Could not set API! error: %d", eglGetError()); | |
goto _fail1; | |
} | |
// Get an appropriate EGL framebuffer configuration | |
EGLConfig config; | |
EGLint numConfigs; | |
static const EGLint framebufferAttributeList[] = | |
{ | |
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, | |
EGL_RED_SIZE, 8, | |
EGL_GREEN_SIZE, 8, | |
EGL_BLUE_SIZE, 8, | |
EGL_ALPHA_SIZE, 8, | |
EGL_DEPTH_SIZE, 24, | |
EGL_STENCIL_SIZE, 8, | |
EGL_NONE | |
}; | |
eglChooseConfig(s_display, framebufferAttributeList, &config, 1, &numConfigs); | |
if (numConfigs == 0) | |
{ | |
TRACE("No config found! error: %d", eglGetError()); | |
goto _fail1; | |
} | |
// Create an EGL window surface | |
s_surface = eglCreateWindowSurface(s_display, config, (char*)"", nullptr); | |
if (!s_surface) | |
{ | |
TRACE("Surface creation failed! error: %d", eglGetError()); | |
goto _fail1; | |
} | |
// Create an EGL rendering context | |
static const EGLint contextAttributeList[] = | |
{ | |
EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, | |
EGL_CONTEXT_MAJOR_VERSION_KHR, 4, | |
EGL_CONTEXT_MINOR_VERSION_KHR, 3, | |
EGL_NONE | |
}; | |
s_context = eglCreateContext(s_display, config, EGL_NO_CONTEXT, contextAttributeList); | |
if (!s_context) | |
{ | |
TRACE("Context creation failed! error: %d", eglGetError()); | |
goto _fail2; | |
} | |
// Connect the context to the surface | |
eglMakeCurrent(s_display, s_surface, s_surface, s_context); | |
return true; | |
_fail2: | |
eglDestroySurface(s_display, s_surface); | |
s_surface = nullptr; | |
_fail1: | |
eglTerminate(s_display); | |
s_display = nullptr; | |
_fail0: | |
return false; | |
} | |
static void deinitEgl() | |
{ | |
if (s_display) | |
{ | |
eglMakeCurrent(s_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | |
if (s_context) | |
{ | |
eglDestroyContext(s_display, s_context); | |
s_context = nullptr; | |
} | |
if (s_surface) | |
{ | |
eglDestroySurface(s_display, s_surface); | |
s_surface = nullptr; | |
} | |
eglTerminate(s_display); | |
s_display = nullptr; | |
} | |
} | |
//----------------------------------------------------------------------------- | |
// Main program | |
//----------------------------------------------------------------------------- | |
static void setMesaConfig() | |
{ | |
// Uncomment below to disable error checking and save CPU time (useful for production): | |
//setenv("MESA_NO_ERROR", "1", 1); | |
// Uncomment below to enable Mesa logging: | |
//setenv("EGL_LOG_LEVEL", "debug", 1); | |
//setenv("MESA_VERBOSE", "all", 1); | |
//setenv("NOUVEAU_MESA_DEBUG", "1", 1); | |
// Uncomment below to enable shader debugging in Nouveau: | |
//setenv("NV50_PROG_OPTIMIZE", "0", 1); | |
//setenv("NV50_PROG_DEBUG", "1", 1); | |
//setenv("NV50_PROG_CHIPSET", "0x120", 1); | |
} | |
static const char* const vertexShaderSource = R"text( | |
#version 320 es | |
precision mediump float; | |
layout (location = 0) in vec3 inPos; | |
layout (location = 1) in vec2 inTexCoord; | |
layout (location = 2) in vec3 inNormal; | |
out vec3 vtxTexCoord; | |
out vec4 vtxNormalQuat; | |
out vec3 vtxView; | |
uniform mat4 mdlvMtx; | |
uniform mat4 projMtx; | |
void main() | |
{ | |
// Calculate position | |
vec4 pos = mdlvMtx * vec4(inPos, 1.0); | |
vtxView = -pos.xyz; | |
gl_Position = projMtx * pos; | |
// Calculate normalquat | |
vec3 normal = normalize(mat3(mdlvMtx) * inNormal); | |
float z = (1.0 + normal.z) / 2.0; | |
vtxNormalQuat = vec4(1.0, 0.0, 0.0, 0.0); | |
if (z > 0.0) | |
{ | |
vtxNormalQuat.z = sqrt(z); | |
vtxNormalQuat.xy = normal.xy / (2.0 * vtxNormalQuat.z); | |
} | |
// Calculate texcoord | |
vtxTexCoord = inPos; | |
} | |
)text"; | |
static const char* const fragmentShaderSource = R"text( | |
#version 320 es | |
precision mediump float; | |
in vec3 vtxTexCoord; | |
in vec4 vtxNormalQuat; | |
in vec3 vtxView; | |
out vec4 fragColor; | |
uniform vec4 lightPos; | |
uniform vec3 ambient; | |
uniform vec3 diffuse; | |
uniform vec4 specular; // w component is shininess | |
uniform samplerCube tex_diffuse; | |
// Rotate the vector v by the quaternion q | |
vec3 quatrotate(vec4 q, vec3 v) | |
{ | |
return v + 2.0*cross(q.xyz, cross(q.xyz, v) + q.w*v); | |
} | |
void main() | |
{ | |
// Extract normal from quaternion | |
vec4 normquat = normalize(vtxNormalQuat); | |
vec3 normal = quatrotate(normquat, vec3(0.0, 0.0, 1.0)); | |
vec3 lightVec; | |
if (lightPos.w != 0.0) | |
lightVec = normalize(lightPos.xyz + vtxView); | |
else | |
lightVec = normalize(lightPos.xyz); | |
vec3 viewVec = normalize(vtxView); | |
vec3 halfVec = normalize(viewVec + lightVec); | |
float diffuseFactor = max(dot(lightVec, normal), 0.0); | |
float specularFactor = pow(max(dot(normal, halfVec), 0.0), specular.w); | |
vec4 texDiffuseColor = texture(tex_diffuse, vtxTexCoord); | |
vec3 fragLightColor = ambient + diffuseFactor*diffuse*texDiffuseColor.rgb + specularFactor*specular.xyz; | |
fragColor = vec4(min(fragLightColor, 1.0), texDiffuseColor.a); | |
} | |
)text"; | |
static GLuint createAndCompileShader(GLenum type, const char* source) | |
{ | |
GLint success; | |
GLchar msg[512]; | |
GLuint handle = glCreateShader(type); | |
if (!handle) | |
{ | |
TRACE("%u: cannot create shader", type); | |
return 0; | |
} | |
glShaderSource(handle, 1, &source, nullptr); | |
glCompileShader(handle); | |
glGetShaderiv(handle, GL_COMPILE_STATUS, &success); | |
if (success == GL_FALSE) | |
{ | |
glGetShaderInfoLog(handle, sizeof(msg), nullptr, msg); | |
TRACE("%u: %s\n", type, msg); | |
glDeleteShader(handle); | |
return 0; | |
} | |
return handle; | |
} | |
typedef struct | |
{ | |
float position[3]; | |
float texcoord[2]; | |
float normal[3]; | |
} Vertex; | |
static const Vertex vertex_list[] = | |
{ | |
// First face (PZ) | |
// First triangle | |
{ {-0.5f, -0.5f, +0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, +1.0f} }, | |
{ {+0.5f, -0.5f, +0.5f}, {1.0f, 0.0f}, {0.0f, 0.0f, +1.0f} }, | |
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, +1.0f} }, | |
// Second triangle | |
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, +1.0f} }, | |
{ {-0.5f, +0.5f, +0.5f}, {0.0f, 1.0f}, {0.0f, 0.0f, +1.0f} }, | |
{ {-0.5f, -0.5f, +0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, +1.0f} }, | |
// Second face (MZ) | |
// First triangle | |
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} }, | |
{ {-0.5f, +0.5f, -0.5f}, {1.0f, 0.0f}, {0.0f, 0.0f, -1.0f} }, | |
{ {+0.5f, +0.5f, -0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f} }, | |
// Second triangle | |
{ {+0.5f, +0.5f, -0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f} }, | |
{ {+0.5f, -0.5f, -0.5f}, {0.0f, 1.0f}, {0.0f, 0.0f, -1.0f} }, | |
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} }, | |
// Third face (PX) | |
// First triangle | |
{ {+0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} }, | |
{ {+0.5f, +0.5f, -0.5f}, {1.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} }, | |
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} }, | |
// Second triangle | |
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} }, | |
{ {+0.5f, -0.5f, +0.5f}, {0.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} }, | |
{ {+0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} }, | |
// Fourth face (MX) | |
// First triangle | |
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} }, | |
{ {-0.5f, -0.5f, +0.5f}, {1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} }, | |
{ {-0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} }, | |
// Second triangle | |
{ {-0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} }, | |
{ {-0.5f, +0.5f, -0.5f}, {0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} }, | |
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} }, | |
// Fifth face (PY) | |
// First triangle | |
{ {-0.5f, +0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, +1.0f, 0.0f} }, | |
{ {-0.5f, +0.5f, +0.5f}, {1.0f, 0.0f}, {0.0f, +1.0f, 0.0f} }, | |
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, +1.0f, 0.0f} }, | |
// Second triangle | |
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, +1.0f, 0.0f} }, | |
{ {+0.5f, +0.5f, -0.5f}, {0.0f, 1.0f}, {0.0f, +1.0f, 0.0f} }, | |
{ {-0.5f, +0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, +1.0f, 0.0f} }, | |
// Sixth face (MY) | |
// First triangle | |
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f} }, | |
{ {+0.5f, -0.5f, -0.5f}, {1.0f, 0.0f}, {0.0f, -1.0f, 0.0f} }, | |
{ {+0.5f, -0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, -1.0f, 0.0f} }, | |
// Second triangle | |
{ {+0.5f, -0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, -1.0f, 0.0f} }, | |
{ {-0.5f, -0.5f, +0.5f}, {0.0f, 1.0f}, {0.0f, -1.0f, 0.0f} }, | |
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f} }, | |
}; | |
#define vertex_list_count (sizeof(vertex_list)/sizeof(vertex_list[0])) | |
static GLuint s_program; | |
static GLuint s_vao, s_vbo; | |
static GLuint s_tex; | |
static GLint loc_mdlvMtx, loc_projMtx; | |
static GLint loc_lightPos, loc_ambient, loc_diffuse, loc_specular, loc_tex_diffuse; | |
static u64 s_startTicks; | |
static void sceneInit() | |
{ | |
GLint vsh = createAndCompileShader(GL_VERTEX_SHADER, vertexShaderSource); | |
GLint fsh = createAndCompileShader(GL_FRAGMENT_SHADER, fragmentShaderSource); | |
s_program = glCreateProgram(); | |
glAttachShader(s_program, vsh); | |
glAttachShader(s_program, fsh); | |
glLinkProgram(s_program); | |
GLint success; | |
glGetProgramiv(s_program, GL_LINK_STATUS, &success); | |
if (success == GL_FALSE) | |
{ | |
char buf[512]; | |
glGetProgramInfoLog(s_program, sizeof(buf), nullptr, buf); | |
TRACE("Link error: %s", buf); | |
} | |
glDeleteShader(vsh); | |
glDeleteShader(fsh); | |
loc_mdlvMtx = glGetUniformLocation(s_program, "mdlvMtx"); | |
loc_projMtx = glGetUniformLocation(s_program, "projMtx"); | |
loc_lightPos = glGetUniformLocation(s_program, "lightPos"); | |
loc_ambient = glGetUniformLocation(s_program, "ambient"); | |
loc_diffuse = glGetUniformLocation(s_program, "diffuse"); | |
loc_specular = glGetUniformLocation(s_program, "specular"); | |
loc_tex_diffuse = glGetUniformLocation(s_program, "tex_diffuse"); | |
glEnable(GL_DEPTH_TEST); | |
glDepthFunc(GL_LESS); | |
glGenVertexArrays(1, &s_vao); | |
glGenBuffers(1, &s_vbo); | |
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). | |
glBindVertexArray(s_vao); | |
glBindBuffer(GL_ARRAY_BUFFER, s_vbo); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_list), vertex_list, GL_STATIC_DRAW); | |
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position)); | |
glEnableVertexAttribArray(0); | |
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texcoord)); | |
glEnableVertexAttribArray(1); | |
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal)); | |
glEnableVertexAttribArray(2); | |
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other | |
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. | |
glBindVertexArray(0); | |
// Textures | |
s_tex = SOIL_load_OGL_cubemap( | |
"Right.png", | |
"Left.png", | |
"Top.png", | |
"Bottom.png", | |
"Back.png", | |
"Front.png", | |
0, 0, 0 | |
); | |
// Uniforms | |
glUseProgram(s_program); | |
auto projMtx = glm::perspective(40.0f*TAU/360.0f, 1280.0f/720.0f, 0.01f, 1000.0f); | |
glUniformMatrix4fv(loc_projMtx, 1, GL_FALSE, glm::value_ptr(projMtx)); | |
glUniform4f(loc_lightPos, 0.0f, 0.0f, 0.5f, 1.0f); | |
glUniform3f(loc_ambient, 0.1f, 0.1f, 0.1f); | |
glUniform3f(loc_diffuse, 0.4f, 0.4f, 0.4f); | |
glUniform4f(loc_specular, 0.5f, 0.5f, 0.5f, 20.0f); | |
glUniform1i(loc_tex_diffuse, 0); // texunit 0 | |
s_startTicks = armGetSystemTick(); | |
} | |
static float getTime() | |
{ | |
u64 elapsed = armGetSystemTick() - s_startTicks; | |
return (elapsed * 625 / 12) / 1000000000.0; | |
} | |
static void sceneUpdate() | |
{ | |
glm::mat4 mdlvMtx{1.0}; | |
mdlvMtx = glm::translate(mdlvMtx, glm::vec3{0.0f, 0.0f, -3.0f}); | |
mdlvMtx = glm::rotate(mdlvMtx, getTime() * TAU * 0.234375f, glm::vec3{1.0f, 0.0f, 0.0f}); | |
mdlvMtx = glm::rotate(mdlvMtx, getTime() * TAU * 0.234375f / 2.0f, glm::vec3{0.0f, 1.0f, 0.0f}); | |
glUniformMatrix4fv(loc_mdlvMtx, 1, GL_FALSE, glm::value_ptr(mdlvMtx)); | |
} | |
static void sceneRender() | |
{ | |
glClearColor(0x68/255.0f, 0xB0/255.0f, 0xD8/255.0f, 1.0f); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
// draw our textured cube | |
glBindVertexArray(s_vao); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized | |
glDrawArrays(GL_TRIANGLES, 0, vertex_list_count); | |
} | |
static void sceneExit() | |
{ | |
glDeleteTextures(1, &s_tex); | |
glDeleteBuffers(1, &s_vbo); | |
glDeleteVertexArrays(1, &s_vao); | |
glDeleteProgram(s_program); | |
} | |
int main(int argc, char* argv[]) | |
{ | |
// Set mesa configuration (useful for debugging) | |
setMesaConfig(); | |
// Initialize EGL | |
if (!initEgl()) | |
return EXIT_FAILURE; | |
// Load OpenGL routines using glad | |
gladLoadGL(); | |
// Initialize our scene | |
sceneInit(); | |
// Main graphics loop | |
while (appletMainLoop()) | |
{ | |
// Get and process input | |
hidScanInput(); | |
u32 kDown = hidKeysDown(CONTROLLER_P1_AUTO); | |
if (kDown & KEY_PLUS) | |
break; | |
// Update our scene | |
sceneUpdate(); | |
// Render stuff! | |
sceneRender(); | |
eglSwapBuffers(s_display, s_surface); | |
} | |
// Deinitialize our scene | |
sceneExit(); | |
// Deinitialize EGL | |
deinitEgl(); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment