My step by step guides for SDL3 to build for Android and WebAssembly

Tutorial: How to add shaders and shader problem files to the CMake project of sdl3-sample

if(CMAKE_SYSTEM_NAME MATCHES Emscripten)
	set(CMAKE_EXECUTABLE_SUFFIX ".html" CACHE INTERNAL "")

    target_link_options("${EXECUTABLE_NAME}" PRIVATE "SHELL:--embed-file ${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders/color.vert@/assets/shaders/color.vert")
    set_property(TARGET "${EXECUTABLE_NAME}" APPEND PROPERTY LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders/color.vert")

    target_link_options("${EXECUTABLE_NAME}" PRIVATE "SHELL:--embed-file ${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders/color.frag@/assets/shaders/color.frag")
    set_property(TARGET "${EXECUTABLE_NAME}" APPEND PROPERTY LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders/color.frag")

endif()
  • Create the sdl3-sample/src/shader_program.cpp and shader_probram.cpp files inside of the sdl3-sample/src folder
  • Add the sdl3-sample/src/shader_program.cpp line to the sdl3-sample/CMakeLists.txt file:
target_sources(${EXECUTABLE_NAME} 
PRIVATE 
    src/main.cpp
    src/iosLaunchScreen.storyboard
    src/Sample.appxManifest
    src/shader_program.cpp
)
  • Copy the next content to the files:

assets/shaders/color.vert

attribute vec3 aPosition;

uniform mat4 uMvpMatrix;

void main()
{
    gl_Position = uMvpMatrix * vec4(aPosition, 1.0);
}

assets/shaders/color.frag

#ifdef GL_ES
precision mediump float;
#endif

uniform vec3 uColor;

void main()
{
    gl_FragColor = vec4(uColor, 1.0);
}

src/shader_program.h

#ifndef SHADER_PROGRAM_H
#define SHADER_PROGRAM_H

#include <SDL3/SDL_opengles2.h>
#include <string>

// Helper function for creating shaders
GLuint createShader(const char *shaderSource, int shaderType);

// Helper function for creating a shader program
GLuint createShaderProgram(const std::string vShaderPath, const std::string fShaderPath);

#endif // SHADER_PROGRAM_H

src/shader_program.cpp

#include "shader_program.h"

#include <iostream>
#include <fstream>
#include <iostream>
#include <sstream>

// Helper function for creating shaders
GLuint createShader(const char *shaderSource, int shaderType)
{
    GLuint shader = glCreateShader(shaderType);
    glShaderSource(shader, 1, &shaderSource, NULL);
    glCompileShader(shader);
    GLint status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
        std::vector<GLchar> errorLog(maxLength);
        glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
        glDeleteShader(shader); // Don't leak the shader
        std::cout << &(errorLog[0]) << std::endl;
        std::cout << shaderSource << std::endl;
    }
    return shader;
}

// Helper function for creating a shader program
GLuint createShaderProgram(const std::string vShaderPath,
    const std::string fShaderPath)
{
    std::ifstream vf(vShaderPath);
    if (!vf.is_open())
    {
        std::cout << "Failed to open the file: " << vShaderPath << std::endl;
        return 0;
    }
    std::stringstream vsstr;
    vf >> vsstr.rdbuf();
    std::string vContent = vsstr.str();
    vf.close();

    std::ifstream ff(fShaderPath);
    if (!ff.is_open())
    {
        std::cout << "Failed to open the file: " << fShaderPath << std::endl;
        return 0;
    }
    std::stringstream fsstr;
    ff >> fsstr.rdbuf();
    std::string fContent = fsstr.str();
    ff.close();

    GLuint program = glCreateProgram();
    GLuint vShader = createShader(vContent.c_str(), GL_VERTEX_SHADER);
    GLuint fShader = createShader(fContent.c_str(), GL_FRAGMENT_SHADER);

    glAttachShader(program, vShader);
    glAttachShader(program, fShader);
    glLinkProgram(program);
    glUseProgram(program);

    return program;
}