Skip to content

Instantly share code, notes, and snippets.

@BaronKiko
Last active February 28, 2019 21:10
Show Gist options
  • Save BaronKiko/6a77f0b84802feb9b4e14ca8f40578fb to your computer and use it in GitHub Desktop.
Save BaronKiko/6a77f0b84802feb9b4e14ca8f40578fb to your computer and use it in GitHub Desktop.
SOIL2 error
#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