Skip to content

Commit

Permalink
Add ARB_vertex_program / ARB_fragment_program example.
Browse files Browse the repository at this point in the history
This is the old low-level shader API. This example is mainly just for
reference. In practice you would rarely want to use this.
  • Loading branch information
mackron committed Mar 15, 2020
1 parent e370b88 commit f125e37
Show file tree
Hide file tree
Showing 4 changed files with 509 additions and 0 deletions.
233 changes: 233 additions & 0 deletions examples/99_ARB_shaders/99_ARB_shaders.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
#include "../glbExamplesCommon.c"

GLuint g_VertShader;
GLuint g_FragShader;

#define VERTEX_ATTRIB_POSITION 0
#define VERTEX_ATTRIB_COLOR 1

const void* vfs_map_file(const char* pFilePath, size_t* pFileSizeInBytes);

static GLenum CreateShader(GLBexample* pExample, GLenum shaderTarget, const char* pShaderString, size_t shaderStringLength, GLuint* pShaderObject)
{
GLuint shaderObject;
GLint shaderErrorPos;

/* Generate shader object. */
glGenProgramsARB(1, &shaderObject);
glBindProgramARB(shaderTarget, shaderObject);

/* Load and compile. */
glProgramStringARB(shaderTarget, GL_PROGRAM_FORMAT_ASCII_ARB, shaderStringLength, pShaderString);

/* Check for any errors. */
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &shaderErrorPos);
if (shaderErrorPos != -1) {
printf("Error in %s shader at position %d: ", (shaderTarget == GL_VERTEX_PROGRAM_ARB) ? "vertex" : "fragment", shaderErrorPos);
printf("%s\n", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
return GL_INVALID_VALUE;
}

return GL_NO_ERROR;
}

static GLenum CreateShaders(GLBexample* pExample)
{
GLenum result;
const void* pVertShaderString;
size_t vertShaderStringLen;
const void* pFragShaderString;
size_t fragShaderStringLen;

pVertShaderString = vfs_map_file("VertexShader.txt", &vertShaderStringLen);
if (pVertShaderString == NULL) {
printf("Failed to load vertex shader.\n");
return GL_INVALID_VALUE;
}

pFragShaderString = vfs_map_file("FragmentShader.txt", &fragShaderStringLen);
if (pVertShaderString == NULL) {
printf("Failed to load fragment shader.\n");
return GL_INVALID_VALUE;
}

result = CreateShader(pExample, GL_VERTEX_PROGRAM_ARB, pVertShaderString, vertShaderStringLen, &g_VertShader);
if (result != GL_NO_ERROR) {
return result;
}

result = CreateShader(pExample, GL_FRAGMENT_PROGRAM_ARB, pFragShaderString, fragShaderStringLen, &g_FragShader);
if (result != GL_NO_ERROR) {
glDeleteProgramsARB(1, &g_VertShader);
return result;
}

return GL_NO_ERROR;
}

GLenum onInit(GLBexample* pExample)
{
GLenum result;

/* We first need to check that we support ARB shaders. */
if (!glbIsExtensionSupported(&pExample->gl, "GL_ARB_vertex_program")) {
printf("GL_ARB_vertex_program not supported.\n");
return GL_INVALID_OPERATION;
}
if (!glbIsExtensionSupported(&pExample->gl, "GL_ARB_fragment_program")) {
printf("GL_ARB_fragment_program not supported.\n");
return GL_INVALID_OPERATION;
}

result = CreateShaders(pExample);
if (result != GL_NO_ERROR) {
return result;
}

/* Shaders have been created. Initialize some state. */
glEnable(GL_VERTEX_PROGRAM_ARB);
glEnable(GL_FRAGMENT_PROGRAM_ARB);

return GL_NO_ERROR;
}

void onDraw(GLBexample* pExample)
{
glClearColor(0.2f, 0.5f, 0.8f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

/* We can now set the MVP matrix. In this example we always use the identity matrix, but in a real program you would make this a variable. */
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0, 1, 0, 0, 0);
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 1, 0, 1, 0, 0);
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 2, 0, 0, 1, 0);
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 3, 0, 0, 0, 1);

glBegin(GL_TRIANGLES);
{
glVertexAttrib3f(VERTEX_ATTRIB_COLOR, 1, 0, 0);
glVertexAttrib2f(VERTEX_ATTRIB_POSITION, 0.0f, 0.5f);
glVertexAttrib3f(VERTEX_ATTRIB_COLOR, 0, 1, 0);
glVertexAttrib2f(VERTEX_ATTRIB_POSITION, -0.5f, -0.5f);
glVertexAttrib3f(VERTEX_ATTRIB_COLOR, 0, 0, 1);
glVertexAttrib2f(VERTEX_ATTRIB_POSITION, 0.5f, -0.5f);
}
glEnd();
}

void onSize(GLBexample* pExample, GLsizei sizeX, GLsizei sizeY)
{
pExample->gl.glViewport(0, 0, sizeX, sizeY);
}

int main(int argc, char** argv)
{
GLenum result;
GLBexampleconfig config;
GLBexample example;

glbZeroObject(&config);
config.pGLBConfig = NULL;
config.pUserData = NULL;
config.onInit = onInit;
config.onDraw = onDraw;
config.onSize = onSize;

result = glbExampleInit(&example, &config);
if (result != GL_NO_ERROR) {
printf("Failed to initialize example.\n");
return -1;
}

glbExampleRun(&example);

/* Done. */
glbExampleUninit(&example);
return 0;
}


static unsigned char g_vfsFileData[] = {
0x21, 0x21, 0x41, 0x52, 0x42, 0x66, 0x70, 0x31, 0x2E, 0x30, 0x0A, 0x0A, 0x23, 0x20, 0x49, 0x6E,
0x70, 0x75, 0x74, 0x73, 0x0A, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x20, 0x69, 0x43, 0x6F, 0x6C,
0x20, 0x3D, 0x20, 0x66, 0x72, 0x61, 0x67, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x74, 0x65, 0x78, 0x63,
0x6F, 0x6F, 0x72, 0x64, 0x5B, 0x30, 0x5D, 0x3B, 0x0A, 0x0A, 0x23, 0x20, 0x4F, 0x75, 0x74, 0x70,
0x75, 0x74, 0x73, 0x0A, 0x4F, 0x55, 0x54, 0x50, 0x55, 0x54, 0x20, 0x6F, 0x43, 0x6F, 0x6C, 0x20,
0x3D, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x2E, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3B, 0x0A,
0x0A, 0x4D, 0x4F, 0x56, 0x20, 0x6F, 0x43, 0x6F, 0x6C, 0x2C, 0x20, 0x69, 0x43, 0x6F, 0x6C, 0x3B,
0x0A, 0x0A, 0x45, 0x4E, 0x44, 0x00, 0x00, 0x00, 0x21, 0x21, 0x41, 0x52, 0x42, 0x76, 0x70, 0x31,
0x2E, 0x30, 0x0A, 0x0A, 0x23, 0x20, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x73, 0x0A, 0x41, 0x54, 0x54,
0x52, 0x49, 0x42, 0x20, 0x69, 0x50, 0x6F, 0x73, 0x20, 0x3D, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65,
0x78, 0x2E, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x5B, 0x30, 0x5D, 0x3B, 0x0A, 0x41, 0x54, 0x54,
0x52, 0x49, 0x42, 0x20, 0x69, 0x43, 0x6F, 0x6C, 0x20, 0x3D, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65,
0x78, 0x2E, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x5B, 0x31, 0x5D, 0x3B, 0x0A, 0x0A, 0x23, 0x20,
0x4F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x0A, 0x4F, 0x55, 0x54, 0x50, 0x55, 0x54, 0x20, 0x6F,
0x50, 0x6F, 0x73, 0x20, 0x3D, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x2E, 0x70, 0x6F, 0x73,
0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3B, 0x0A, 0x4F, 0x55, 0x54, 0x50, 0x55, 0x54, 0x20, 0x6F, 0x43,
0x6F, 0x6C, 0x20, 0x3D, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x2E, 0x74, 0x65, 0x78, 0x63,
0x6F, 0x6F, 0x72, 0x64, 0x5B, 0x30, 0x5D, 0x3B, 0x0A, 0x0A, 0x23, 0x20, 0x55, 0x6E, 0x69, 0x66,
0x6F, 0x72, 0x6D, 0x73, 0x0A, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x20, 0x6D, 0x76, 0x70, 0x5B, 0x34,
0x5D, 0x20, 0x3D, 0x20, 0x7B, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x2E, 0x6C, 0x6F,
0x63, 0x61, 0x6C, 0x5B, 0x30, 0x5D, 0x2C, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x2E,
0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x5B, 0x31, 0x5D, 0x2C, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61,
0x6D, 0x2E, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x5B, 0x32, 0x5D, 0x2C, 0x20, 0x70, 0x72, 0x6F, 0x67,
0x72, 0x61, 0x6D, 0x2E, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x5B, 0x33, 0x5D, 0x20, 0x7D, 0x3B, 0x0A,
0x0A, 0x44, 0x50, 0x34, 0x20, 0x6F, 0x50, 0x6F, 0x73, 0x2E, 0x78, 0x2C, 0x20, 0x69, 0x50, 0x6F,
0x73, 0x2C, 0x20, 0x6D, 0x76, 0x70, 0x5B, 0x30, 0x5D, 0x3B, 0x0D, 0x0A, 0x44, 0x50, 0x34, 0x20,
0x6F, 0x50, 0x6F, 0x73, 0x2E, 0x79, 0x2C, 0x20, 0x69, 0x50, 0x6F, 0x73, 0x2C, 0x20, 0x6D, 0x76,
0x70, 0x5B, 0x31, 0x5D, 0x3B, 0x0D, 0x0A, 0x44, 0x50, 0x34, 0x20, 0x6F, 0x50, 0x6F, 0x73, 0x2E,
0x7A, 0x2C, 0x20, 0x69, 0x50, 0x6F, 0x73, 0x2C, 0x20, 0x6D, 0x76, 0x70, 0x5B, 0x32, 0x5D, 0x3B,
0x0D, 0x0A, 0x44, 0x50, 0x34, 0x20, 0x6F, 0x50, 0x6F, 0x73, 0x2E, 0x77, 0x2C, 0x20, 0x69, 0x50,
0x6F, 0x73, 0x2C, 0x20, 0x6D, 0x76, 0x70, 0x5B, 0x33, 0x5D, 0x3B, 0x0A, 0x0A, 0x4D, 0x4F, 0x56,
0x20, 0x6F, 0x43, 0x6F, 0x6C, 0x2C, 0x20, 0x69, 0x43, 0x6F, 0x6C, 0x3B, 0x0A, 0x0A, 0x45, 0x4E,
0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

typedef struct
{
const char* pFilePath;
size_t sizeInBytes;
size_t dataOffsetInBytes;
} vfs_file_data;

static vfs_file_data g_vfsCentralDirectory[] = {
{"FragmentShader.txt", 117, 0},
{"VertexShader.txt", 393, 120}
};

static size_t vfs_find_file(const char* pFilePath)
{
size_t iFile;

if (pFilePath == NULL) {
return (size_t)-1;
}

for (iFile = 0; iFile < sizeof(g_vfsCentralDirectory)/sizeof(g_vfsCentralDirectory[0]); iFile += 1) {
int cmpresult = strcmp(g_vfsCentralDirectory[iFile].pFilePath, pFilePath);
if (cmpresult == 0) {
return iFile;
}
}

return (size_t)-1;
}

const void* vfs_map_file(const char* pFilePath, size_t* pFileSizeInBytes)
{
size_t iFile;

if (pFileSizeInBytes != NULL) {
*pFileSizeInBytes = 0;
}

iFile = vfs_find_file(pFilePath);
if (iFile == (size_t)-1) {
return NULL;
}

if (pFileSizeInBytes != NULL) {
*pFileSizeInBytes = g_vfsCentralDirectory[iFile].sizeInBytes;
}

return &g_vfsFileData[g_vfsCentralDirectory[iFile].dataOffsetInBytes];
}
11 changes: 11 additions & 0 deletions examples/99_ARB_shaders/resources/FragmentShader.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
!!ARBfp1.0

# Inputs
ATTRIB iCol = fragment.texcoord[0];

# Outputs
OUTPUT oCol = result.color;

MOV oCol, iCol;

END
21 changes: 21 additions & 0 deletions examples/99_ARB_shaders/resources/VertexShader.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
!!ARBvp1.0

# Inputs
ATTRIB iPos = vertex.attrib[0];
ATTRIB iCol = vertex.attrib[1];

# Outputs
OUTPUT oPos = result.position;
OUTPUT oCol = result.texcoord[0];

# Uniforms
PARAM mvp[4] = { program.local[0], program.local[1], program.local[2], program.local[3] };

DP4 oPos.x, iPos, mvp[0];
DP4 oPos.y, iPos, mvp[1];
DP4 oPos.z, iPos, mvp[2];
DP4 oPos.w, iPos, mvp[3];

MOV oCol, iCol;

END
Loading

0 comments on commit f125e37

Please sign in to comment.