Added super simple shaders, does render videos now

This commit is contained in:
Daniel Gibson 2017-01-22 04:59:18 +01:00
parent 56661fd43f
commit 678410bfb4
9 changed files with 953 additions and 40 deletions

View File

@ -850,6 +850,7 @@ REFGL3_OBJS_ := \
src/client/refresh/gl3/gl3_model.o \
src/client/refresh/gl3/gl3_sdl.o \
src/client/refresh/gl3/gl3_warp.o \
src/client/refresh/gl3/gl3_shaders.o \
src/client/refresh/files/pcx.o \
src/client/refresh/files/stb.o \
src/client/refresh/files/wal.o \

View File

@ -36,6 +36,86 @@ GL3_Draw_InitLocal(void)
{
/* load console characters */
draw_chars = GL3_FindImage("pics/conchars.pcx", it_pic);
glGenVertexArrays(1, &gl3state.vao2D);
glBindVertexArray(gl3state.vao2D);
glGenBuffers(1, &gl3state.vbo2D);
glBindBuffer(GL_ARRAY_BUFFER, gl3state.vbo2D); // TODO ??
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void
GL3_Draw_ShutdownLocal(void)
{
glDeleteBuffers(1, &gl3state.vbo2D);
gl3state.vbo2D = 0;
glDeleteVertexArrays(1, &gl3state.vao2D);
gl3state.vao2D = 0;
}
/*
* Draws one 8*8 graphics character with 0 being transparent.
* It can be clipped to the top of the screen to allow the console to be
* smoothly scrolled off.
*/
void
GL3_Draw_CharScaled(int x, int y, int num, float scale)
{
STUB_ONCE("TODO: Implement!");
#if 0
int row, col;
float frow, fcol, size, scaledSize;
num &= 255;
if ((num & 127) == 32)
{
return; /* space */
}
if (y <= -8)
{
return; /* totally off screen */
}
row = num >> 4;
col = num & 15;
frow = row * 0.0625;
fcol = col * 0.0625;
size = 0.0625;
scaledSize = 8*scale;
R_Bind(draw_chars->texnum);
GLfloat vtx[] = {
x, y,
x + scaledSize, y,
x + scaledSize, y + scaledSize,
x, y + scaledSize
};
GLfloat tex[] = {
fcol, frow,
fcol + size, frow,
fcol + size, frow + size,
fcol, frow + size
};
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, vtx );
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif // 0
}
gl3image_t *
@ -62,7 +142,7 @@ GL3_Draw_GetPicSize(int *w, int *h, char *pic)
{
gl3image_t *gl;
gl = GL3Draw_FindPic(pic);
gl = GL3_Draw_FindPic(pic);
if (!gl)
{
@ -74,6 +154,296 @@ GL3_Draw_GetPicSize(int *w, int *h, char *pic)
*h = gl->height;
}
void
GL3_Draw_StretchPic(int x, int y, int w, int h, char *pic)
{
STUB_ONCE("TODO: Implement!");
#if 0
image_t *gl;
gl = RDraw_FindPic(pic);
if (!gl)
{
R_Printf(PRINT_ALL, "Can't find pic: %s\n", pic);
return;
}
if (scrap_dirty)
{
Scrap_Upload();
}
R_Bind(gl->texnum);
GLfloat vtx[] = {
x, y,
x + w, y,
x + w, y + h,
x, y + h
};
GLfloat tex[] = {
gl->sl, gl->tl,
gl->sh, gl->tl,
gl->sh, gl->th,
gl->sl, gl->th
};
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, vtx );
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif // 0
}
void
GL3_Draw_PicScaled(int x, int y, char *pic, float factor)
{
STUB_ONCE("TODO: Implement!");
#if 0
image_t *gl;
gl = RDraw_FindPic(pic);
if (!gl)
{
R_Printf(PRINT_ALL, "Can't find pic: %s\n", pic);
return;
}
if (scrap_dirty)
{
Scrap_Upload();
}
R_Bind(gl->texnum);
GLfloat vtx[] = {
x, y,
x + gl->width * factor, y,
x + gl->width * factor, y + gl->height * factor,
x, y + gl->height * factor
};
GLfloat tex[] = {
gl->sl, gl->tl,
gl->sh, gl->tl,
gl->sh, gl->th,
gl->sl, gl->th
};
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, vtx );
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif // 0
}
/*
* This repeats a 64*64 tile graphic to fill
* the screen around a sized down
* refresh window.
*/
void
GL3_Draw_TileClear(int x, int y, int w, int h, char *pic)
{
STUB_ONCE("TODO: Implement!");
#if 0
image_t *image;
image = RDraw_FindPic(pic);
if (!image)
{
R_Printf(PRINT_ALL, "Can't find pic: %s\n", pic);
return;
}
R_Bind(image->texnum);
GLfloat vtx[] = {
x, y,
x + w, y,
x + w, y + h,
x, y + h
};
GLfloat tex[] = {
x / 64.0, y / 64.0,
( x + w ) / 64.0, y / 64.0,
( x + w ) / 64.0, ( y + h ) / 64.0,
x / 64.0, ( y + h ) / 64.0
};
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, vtx );
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif // 0
}
/*
* Fills a box of pixels with a single color
*/
void
GL3_Draw_Fill(int x, int y, int w, int h, int c)
{
STUB_ONCE("TODO: Implement!");
#if 0
union
{
unsigned c;
byte v[4];
} color;
if ((unsigned)c > 255)
{
ri.Sys_Error(ERR_FATAL, "Draw_Fill: bad color");
}
glDisable(GL_TEXTURE_2D);
color.c = d_8to24table[c];
glColor4f(color.v [ 0 ] / 255.0, color.v [ 1 ] / 255.0,
color.v [ 2 ] / 255.0, 1);
GLfloat vtx[] = {
x, y,
x + w, y,
x + w, y + h,
x, y + h
};
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, vtx );
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glColor4f( 1, 1, 1, 1 );
glEnable(GL_TEXTURE_2D);
#endif // 0
}
void
GL3_Draw_FadeScreen(void)
{
STUB_ONCE("TODO: Implement!");
#if 0
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glColor4f(0, 0, 0, 0.8);
GLfloat vtx[] = {
0, 0,
vid.width, 0,
vid.width, vid.height,
0, vid.height
};
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, vtx );
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glColor4f(1, 1, 1, 1);
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
#endif // 0
}
void
GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
{
byte *source;
float hscale = 1.0f;
int frac, fracstep;
int i, j, trows;
int row;
GLfloat vBuf[] = {
// posX, posY, texS, texT
x, y + h, 0.0f, 1.0f,
x, y, 0.0f, 0.0f,
x + w, y + h, 1.0f, 1.0f,
x + w, y, 1.0f, 0.0f,
};
GL3_Bind(0);
unsigned image32[320*240]; /* was 256 * 256, but we want a bit more space */
unsigned* img = image32;
if(cols*rows > 320*240)
{
/* in case there is a bigger video after all,
* malloc enough space to hold the frame */
img = (unsigned*)malloc(cols*rows*4);
}
for(i=0; i<rows; ++i)
{
int rowOffset = i*cols;
for(j=0; j<cols; ++j)
{
byte palIdx = data[rowOffset+j];
img[rowOffset+j] = gl3_rawpalette[palIdx];
}
}
GLuint glTex;
glGenTextures(1, &glTex);
glBindTexture(GL_TEXTURE_2D, glTex);
glTexImage2D(GL_TEXTURE_2D, 0, gl3_tex_solid_format,
cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
if(img != image32)
{
free(img);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindVertexArray(gl3state.vao2D);
glBindBuffer(GL_ARRAY_BUFFER, gl3state.vbo2D);
glBufferData(GL_ARRAY_BUFFER, sizeof(vBuf), vBuf, GL_STREAM_DRAW);
glEnableVertexAttribArray(gl3state.si2D.attribPosition);
qglVertexAttribPointer(gl3state.si2D.attribPosition, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0);
glEnableVertexAttribArray(gl3state.si2D.attribTexCoord);
qglVertexAttribPointer(gl3state.si2D.attribTexCoord, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), sizeof(float)*2);
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
glDeleteTextures(1, &glTex);
GL3_Bind(0);
}
int
GL3_Draw_GetPalette(void)
{

View File

@ -27,8 +27,6 @@
#include "header/local.h"
extern unsigned d_8to24table[256];
typedef struct
{
char *name;
@ -47,12 +45,6 @@ glmode_t modes[] = {
int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
int gl_filter_max = GL_LINEAR;
// TODO: do we need the following configurable?
static const int gl_solid_format = GL_RGB;
static const int gl_alpha_format = GL_RGBA;
static const int gl_tex_solid_format = GL_RGB;
static const int gl_tex_alpha_format = GL_RGBA;
gl3image_t gl3textures[MAX_GL3TEXTURES];
int numgl3textures;
@ -152,8 +144,8 @@ GL3_Upload32(unsigned *data, int width, int height, qboolean mipmap)
c = width * height;
scan = ((byte *)data) + 3;
samples = gl_solid_format;
comp = gl_tex_solid_format;
samples = gl3_solid_format;
comp = gl3_tex_solid_format;
//upload_width = width; // TODO: remove, probably
//upload_height = height;
@ -164,8 +156,8 @@ GL3_Upload32(unsigned *data, int width, int height, qboolean mipmap)
{
if (*scan != 255)
{
samples = gl_alpha_format;
comp = gl_tex_alpha_format;
samples = gl3_alpha_format;
comp = gl3_tex_alpha_format;
break;
}
}
@ -177,7 +169,7 @@ GL3_Upload32(unsigned *data, int width, int height, qboolean mipmap)
0, GL_RGBA, GL_UNSIGNED_BYTE, data);
//glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, false);
res = (samples == gl_alpha_format);
res = (samples == gl3_alpha_format);
if (mipmap)
{

View File

@ -39,6 +39,8 @@ refimport_t ri;
gl3config_t gl3config;
gl3state_t gl3state;
unsigned gl3_rawpalette[256];
/* screen size info */
refdef_t gl3_newrefdef;
@ -56,6 +58,7 @@ cvar_t *gl_customheight;
cvar_t *vid_gamma;
cvar_t *gl_anisotropic;
cvar_t *gl_norefresh;
cvar_t *gl_nolerp_list;
cvar_t *gl_nobind;
@ -91,6 +94,8 @@ GL3_Register(void)
gl_customwidth = ri.Cvar_Get("gl_customwidth", "1024", CVAR_ARCHIVE);
gl_customheight = ri.Cvar_Get("gl_customheight", "768", CVAR_ARCHIVE);
gl_norefresh = ri.Cvar_Get("gl_norefresh", "0", 0);
/* don't bilerp characters and crosshairs */
gl_nolerp_list = ri.Cvar_Get("gl_nolerp_list", "pics/conchars.pcx pics/ch1.pcx pics/ch2.pcx pics/ch3.pcx", 0);
gl_nobind = ri.Cvar_Get("gl_nobind", "0", 0);
@ -104,7 +109,7 @@ GL3_Register(void)
#if 0 // TODO!
gl_lefthand = ri.Cvar_Get("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
gl_farsee = ri.Cvar_Get("gl_farsee", "0", CVAR_LATCH | CVAR_ARCHIVE);
gl_norefresh = ri.Cvar_Get("gl_norefresh", "0", 0);
//gl_norefresh = ri.Cvar_Get("gl_norefresh", "0", 0);
gl_fullbright = ri.Cvar_Get("gl_fullbright", "0", 0);
gl_drawentities = ri.Cvar_Get("gl_drawentities", "1", 0);
gl_drawworld = ri.Cvar_Get("gl_drawworld", "1", 0);
@ -383,6 +388,16 @@ GL3_Init(void)
GL3_SetDefaultState();
if(GL3_InitShaders())
{
R_Printf(PRINT_ALL, "Loading shaders succeeded!\n");
}
else
{
R_Printf(PRINT_ALL, "Loading shaders failed!\n");
return false;
}
STUB("TODO: Some intensity and gamma stuff that was in R_InitImages()");
registration_sequence = 1; // also from R_InitImages()
@ -440,18 +455,27 @@ GL3_SetGL2D(void)
}
#endif // 0
// FIXME: change to GL3 code!
glViewport(x, y, w, h);
hmm_mat4 transMatr = HMM_Orthographic(0, vid.width, vid.height, 0, -99999, 99999);
glUseProgram(gl3state.si2D.shaderProgram);
glUniformMatrix4fv(gl3state.si2D.uniTransMatrix , 1, GL_FALSE, transMatr.Elements[0]);
// FIXME: change to GL3 code!
#if 0
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, vid.width, vid.height, 0, -99999, 99999);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#endif // 0
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glColor4f(1, 1, 1, 1);
// glEnable(GL_ALPHA_TEST); TODO: do in shader https://www.khronos.org/opengl/wiki/Transparency_Sorting#Alpha_test
// glColor4f(1, 1, 1, 1);
}
/*
@ -670,7 +694,7 @@ GL3_SetLightLevel(void)
{
vec3_t shadelight = {0};
if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
if (gl3_newrefdef.rdflags & RDF_NOWORLDMODEL)
{
return;
}
@ -716,6 +740,169 @@ GL3_RenderFrame(refdef_t *fd)
GL3_SetGL2D();
}
void
GL3_BeginFrame(float camera_separation)
{
STUB_ONCE("TODO: Implement!");
GL3_SetGL2D();
#if 0
gl_state.camera_separation = camera_separation;
/* change modes if necessary */
if (gl_mode->modified)
{
vid_fullscreen->modified = true;
}
// force a vid_restart if gl_stereo has been modified.
if ( gl_state.stereo_mode != gl_stereo->value ) {
// If we've gone from one mode to another with the same special buffer requirements there's no need to restart.
if ( GL_GetSpecialBufferModeForStereoMode( gl_state.stereo_mode ) == GL_GetSpecialBufferModeForStereoMode( gl_stereo->value ) ) {
gl_state.stereo_mode = gl_stereo->value;
}
else
{
R_Printf(PRINT_ALL, "stereo supermode changed, restarting video!\n");
cvar_t *ref;
ref = ri.Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE);
ref->modified = true;
}
}
if (vid_gamma->modified)
{
vid_gamma->modified = false;
if (gl_state.hwgamma)
{
UpdateHardwareGamma();
}
}
// Clamp overbrightbits
if (gl_overbrightbits->modified)
{
if (gl_overbrightbits->value > 2 && gl_overbrightbits->value < 4)
{
ri.Cvar_Set("gl_overbrightbits", "2");
}
else if (gl_overbrightbits->value > 4)
{
ri.Cvar_Set("gl_overbrightbits", "4");
}
gl_overbrightbits->modified = false;
}
/* go into 2D mode */
int x, w, y, h;
qboolean drawing_left_eye = gl_state.camera_separation < 0;
qboolean stereo_split_tb = ((gl_state.stereo_mode == STEREO_SPLIT_VERTICAL) && gl_state.camera_separation);
qboolean stereo_split_lr = ((gl_state.stereo_mode == STEREO_SPLIT_HORIZONTAL) && gl_state.camera_separation);
x = 0;
w = vid.width;
y = 0;
h = vid.height;
if(stereo_split_lr) {
w = w / 2;
x = drawing_left_eye ? 0 : w;
}
if(stereo_split_tb) {
h = h / 2;
y = drawing_left_eye ? h : 0;
}
glViewport(x, y, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, vid.width, vid.height, 0, -99999, 99999);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glColor4f(1, 1, 1, 1);
/* draw buffer stuff */
if (gl_drawbuffer->modified)
{
gl_drawbuffer->modified = false;
if ((gl_state.camera_separation == 0) || gl_state.stereo_mode != STEREO_MODE_OPENGL)
{
if (Q_stricmp(gl_drawbuffer->string, "GL_FRONT") == 0)
{
glDrawBuffer(GL_FRONT);
}
else
{
glDrawBuffer(GL_BACK);
}
}
}
/* texturemode stuff */
if (gl_texturemode->modified || (gl_config.anisotropic && gl_anisotropic->modified))
{
R_TextureMode(gl_texturemode->string);
gl_texturemode->modified = false;
gl_anisotropic->modified = false;
}
if (gl_texturealphamode->modified)
{
R_TextureAlphaMode(gl_texturealphamode->string);
gl_texturealphamode->modified = false;
}
if (gl_texturesolidmode->modified)
{
R_TextureSolidMode(gl_texturesolidmode->string);
gl_texturesolidmode->modified = false;
}
/* clear screen if desired */
R_Clear();
#endif // 0
}
static void
GL3_SetPalette(const unsigned char *palette)
{
int i;
byte *rp = (byte *)gl3_rawpalette;
if (palette)
{
for (i = 0; i < 256; i++)
{
rp[i * 4 + 0] = palette[i * 3 + 0];
rp[i * 4 + 1] = palette[i * 3 + 1];
rp[i * 4 + 2] = palette[i * 3 + 2];
rp[i * 4 + 3] = 0xff;
}
}
else
{
for (i = 0; i < 256; i++)
{
rp[i * 4 + 0] = LittleLong(d_8to24table[i]) & 0xff;
rp[i * 4 + 1] = (LittleLong(d_8to24table[i]) >> 8) & 0xff;
rp[i * 4 + 2] = (LittleLong(d_8to24table[i]) >> 16) & 0xff;
rp[i * 4 + 3] = 0xff;
}
}
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1, 0, 0.5, 0.5);
}
Q2_DLL_EXPORTED refexport_t
GetRefAPI(refimport_t imp)
{
@ -743,20 +930,18 @@ GetRefAPI(refimport_t imp)
re.DrawFindPic = GL3_Draw_FindPic;
re.DrawGetPicSize = GL3_Draw_GetPicSize;
#if 0 // TODO!
re.DrawPicScaled = RDraw_PicScaled;
re.DrawStretchPic = RDraw_StretchPic;
re.DrawPicScaled = GL3_Draw_PicScaled;
re.DrawStretchPic = GL3_Draw_StretchPic;
re.DrawCharScaled = RDraw_CharScaled;
re.DrawTileClear = RDraw_TileClear;
re.DrawFill = RDraw_Fill;
re.DrawFadeScreen = RDraw_FadeScreen;
re.DrawCharScaled = GL3_Draw_CharScaled;
re.DrawTileClear = GL3_Draw_TileClear;
re.DrawFill = GL3_Draw_Fill;
re.DrawFadeScreen = GL3_Draw_FadeScreen;
re.DrawStretchRaw = RDraw_StretchRaw;
re.SetPalette = RI_SetPalette;
re.DrawStretchRaw = GL3_Draw_StretchRaw;
re.SetPalette = GL3_SetPalette;
re.BeginFrame = RI_BeginFrame;
#endif // 0
re.BeginFrame = GL3_BeginFrame;
re.EndFrame = GL3_EndFrame;
return re;

View File

@ -36,8 +36,10 @@ GL3_SetDefaultState(void)
glClearColor(1, 0, 0.5, 0.5);
glDisable(GL_MULTISAMPLE);
glCullFace(GL_FRONT);
glEnable(GL_TEXTURE_2D);
//glEnable(GL_TEXTURE_2D);
// TODO: this must be done in shader instead,
// see https://www.khronos.org/opengl/wiki/Transparency_Sorting#Alpha_test
//glEnable(GL_ALPHA_TEST);
//glAlphaFunc(GL_GREATER, 0.666);

View File

@ -118,13 +118,30 @@ int GL3_PrepareForWindow(void)
return flags;
}
enum {
// for some reason my driver calls the DebugCallback with the following severity
// even though I think it shouldn't for the extension I'm using?
// anyway, my gl headers don't know GL_DEBUG_SEVERITY_NOTIFICATION_* so I define it here
QGL_DEBUG_SEVERITY_NOTIFICATION = 0x826B
};
static void
DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
const GLchar *message, const void *userParam)
const GLchar *message, const void *userParam)
{
const char* sourceStr = "Source: Unknown";
const char* typeStr = "Type: Unknown";
const char* severityStr = "Severity: Unknown";
switch(severity)
{
case QGL_DEBUG_SEVERITY_NOTIFICATION:
// severityStr = "Severity: Note"; break;
return; // ignore these
case GL_DEBUG_SEVERITY_HIGH_ARB: severityStr = "Severity: High"; break;
case GL_DEBUG_SEVERITY_MEDIUM_ARB: severityStr = "Severity: Medium"; break;
case GL_DEBUG_SEVERITY_LOW_ARB: severityStr = "Severity: Low"; break;
}
switch(source)
{
#define SRCCASE(X) case GL_DEBUG_SOURCE_ ## X ## _ARB: sourceStr = "Source: " #X; break;
@ -147,12 +164,6 @@ DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei le
TYPECASE(OTHER);
#undef TYPECASE
}
switch(severity)
{
case GL_DEBUG_SEVERITY_HIGH_ARB: severityStr = "Severity: High"; break;
case GL_DEBUG_SEVERITY_MEDIUM_ARB: severityStr = "Severity: Medium"; break;
case GL_DEBUG_SEVERITY_LOW_ARB: severityStr = "Severity: Low"; break;
}
// use PRINT_ALL - this is only called with gl3_debugcontext != 0 anyway.
R_Printf(PRINT_ALL, "GLDBG %s %s %s: %s\n", sourceStr, typeStr, severityStr, message);

View File

@ -0,0 +1,307 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (C) 2016-2017 Daniel Gibson
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* OpenGL3 refresher: Handling shaders
*
* =======================================================================
*/
#include "header/local.h"
// TODO: remove eprintf() usage
#define eprintf(...) R_Printf(PRINT_ALL, __VA_ARGS__)
#if 0
static const char* vertexSrc = MULTILINE_STRING(#version 150\n
in vec2 position;
// I renamed color to inColor and Color to passColor for more clarity
in vec3 inColor;
// same for texcoord -> inTexCoord, Textcoord -> passTexCoord
in vec2 inTexCoord;
out vec3 passColor;
out vec2 passTexCoord;
void main() {
passColor = inColor;
passTexCoord = inTexCoord;
gl_Position = vec4(position, 0.0, 1.0);
}
);
static const char* fragmentSrc = MULTILINE_STRING(#version 150\n
in vec3 passColor; // I renamed color to passColor (it's from the vertex shader above)
in vec2 passTexCoord; // same for Texcoord -> passTexCoord
out vec4 outColor;
uniform sampler2D tex;
void main()
{
outColor = texture(tex, passTexCoord) * vec4(passColor, 1.0);
//outColor = texture(tex, passTexCoord);
//outColor = vec4(passColor, 1.0);
}
);
#endif // 0
static GLuint
CompileShader(GLenum shaderType, const char* shaderSrc)
{
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &shaderSrc, NULL);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status != GL_TRUE)
{
char buf[2048];
char* bufPtr = buf;
int bufLen = sizeof(buf);
GLint infoLogLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
if(infoLogLength >= bufLen)
{
bufPtr = malloc(infoLogLength+1);
bufLen = infoLogLength+1;
if(bufPtr == NULL)
{
bufPtr = buf;
bufLen = sizeof(buf);
eprintf("WARN: In CompileShader(), malloc(%d) failed!\n", infoLogLength+1);
}
}
glGetShaderInfoLog(shader, bufLen, NULL, bufPtr);
const char* shaderTypeStr = "";
switch(shaderType)
{
case GL_VERTEX_SHADER: shaderTypeStr = "Vertex"; break;
case GL_FRAGMENT_SHADER: shaderTypeStr = "Fragment"; break;
case GL_GEOMETRY_SHADER: shaderTypeStr = "Geometry"; break;
/* not supported in OpenGL3.2 and we're unlikely to need/use them anyway
case GL_COMPUTE_SHADER: shaderTypeStr = "Compute"; break;
case GL_TESS_CONTROL_SHADER: shaderTypeStr = "TessControl"; break;
case GL_TESS_EVALUATION_SHADER: shaderTypeStr = "TessEvaluation"; break;
*/
}
eprintf("ERROR: Compiling %s Shader failed: %s\n", shaderTypeStr, bufPtr);
glDeleteShader(shader);
if(bufPtr != buf) free(bufPtr);
return 0;
}
return shader;
}
static GLuint
CreateShaderProgram(int numShaders, const GLuint* shaders)
{
int i=0;
GLuint shaderProgram = glCreateProgram();
if(shaderProgram == 0)
{
eprintf("ERROR: Couldn't create a new Shader Program!\n");
return 0;
}
for(i=0; i<numShaders; ++i)
{
glAttachShader(shaderProgram, shaders[i]);
}
// the following line is not necessary/implicit (as there's only one output)
// glBindFragDataLocation(shaderProgram, 0, "outColor"); XXX would this even be here?
glLinkProgram(shaderProgram);
GLint status;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &status);
if(status != GL_TRUE)
{
char buf[2048];
char* bufPtr = buf;
int bufLen = sizeof(buf);
GLint infoLogLength;
glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
if(infoLogLength >= bufLen)
{
bufPtr = malloc(infoLogLength+1);
bufLen = infoLogLength+1;
if(bufPtr == NULL)
{
bufPtr = buf;
bufLen = sizeof(buf);
eprintf("WARN: In CreateShaderProgram(), malloc(%d) failed!\n", infoLogLength+1);
}
}
glGetProgramInfoLog(shaderProgram, bufLen, NULL, bufPtr);
eprintf("ERROR: Linking shader program failed: %s\n", bufPtr);
glDeleteProgram(shaderProgram);
if(bufPtr != buf) free(bufPtr);
return 0;
}
for(i=0; i<numShaders; ++i)
{
// after linking, they don't need to be attached anymore.
// no idea why they even are, if they don't have to..
glDetachShader(shaderProgram, shaders[i]);
}
return shaderProgram;
}
#define MULTILINE_STRING(...) #__VA_ARGS__
static const char* vertexSrc2D = MULTILINE_STRING(#version 150\n
in vec2 texCoord;
in vec2 position;
uniform mat4 trans;
out vec2 passTexCoord;
void main()
{
gl_Position = trans * vec4(position, 0.0, 1.0);
passTexCoord = texCoord;
}
);
static const char* fragmentSrc2D = MULTILINE_STRING(#version 150\n
in vec2 passTexCoord;
out vec4 outColor;
uniform sampler2D tex;
void main()
{
// TODO: gamma, intensity
outColor = texture(tex, passTexCoord);
}
);
static const char* vertexSrc2Dcolor = MULTILINE_STRING(#version 150\n
in vec4 color;
in vec2 position;
uniform mat4 trans;
out vec4 passColor;
void main()
{
gl_Position = trans * vec4(position, 0.0, 1.0);
passColor = color;
}
);
static const char* fragmentSrc2Dcolor = MULTILINE_STRING(#version 150\n
in vec4 passColor;
out vec4 outColor;
uniform sampler2D tex;
void main()
{
// TODO: gamma, intensity
outColor = passColor;
}
);
#undef MULTILINE_STRING
qboolean GL3_InitShaders(void)
{
{
GLuint shaders2D[2] = {0};
shaders2D[0] = CompileShader(GL_VERTEX_SHADER, vertexSrc2D);
if(shaders2D[0] == 0) return false;
shaders2D[1] = CompileShader(GL_FRAGMENT_SHADER, fragmentSrc2D);
if(shaders2D[1] == 0)
{
glDeleteShader(shaders2D[0]);
return false;
}
gl3state.si2D.shaderProgram = CreateShaderProgram(2, shaders2D);
// I think the shaders aren't needed anymore once they're linked into the program
glDeleteShader(shaders2D[0]);
glDeleteShader(shaders2D[1]);
if(gl3state.si2D.shaderProgram != 0)
{
glUseProgram(gl3state.si2D.shaderProgram);
gl3state.si2D.attribTexCoord = glGetAttribLocation(gl3state.si2D.shaderProgram, "texCoord");
gl3state.si2D.attribPosition = glGetAttribLocation(gl3state.si2D.shaderProgram, "position");
gl3state.si2D.attribColor = -1;
gl3state.si2D.uniTransMatrix = glGetUniformLocation(gl3state.si2D.shaderProgram, "trans");
}
else
{
return false;
}
}
{
GLuint shaders2Dcol[2] = {0};
shaders2Dcol[0] = CompileShader(GL_VERTEX_SHADER, vertexSrc2Dcolor);
shaders2Dcol[1] = CompileShader(GL_FRAGMENT_SHADER, fragmentSrc2Dcolor);
// TODO: error handling!
gl3state.si2Dcolor.shaderProgram = CreateShaderProgram(2, shaders2Dcol);
// I think the shaders aren't needed anymore once they're linked into the program
glDeleteShader(shaders2Dcol[0]);
glDeleteShader(shaders2Dcol[1]);
if(gl3state.si2Dcolor.shaderProgram != 0)
{
glUseProgram(gl3state.si2Dcolor.shaderProgram);
gl3state.si2Dcolor.attribColor = glGetAttribLocation(gl3state.si2Dcolor.shaderProgram, "color");
gl3state.si2Dcolor.attribPosition = glGetAttribLocation(gl3state.si2Dcolor.shaderProgram, "position");
gl3state.si2Dcolor.attribTexCoord = -1;
gl3state.si2Dcolor.uniTransMatrix = glGetUniformLocation(gl3state.si2Dcolor.shaderProgram, "trans");
}
else
{
// TODO: error handling!
}
}
return true;
}

View File

@ -180,7 +180,8 @@
#pragma warning(disable:4201)
#endif
#ifdef __GNUC__
//#ifdef __GNUC__
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wgnu-anonymous-struct"
#endif
@ -2138,4 +2139,4 @@ operator*=(hmm_mat4 &Left, float Right)
#endif /* HANDMADE_MATH_CPP_MODE */
#endif /* HANDMADE_MATH_IMPLEMENTATION */
#endif /* HANDMADE_MATH_IMPLEMENTATION */

View File

@ -62,6 +62,15 @@ qglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normaliz
glVertexAttribPointer(index, size, type, normalized, stride, (const void*)offset);
}
// TODO: do we need the following configurable?
static const int gl3_solid_format = GL_RGB;
static const int gl3_alpha_format = GL_RGBA;
static const int gl3_tex_solid_format = GL_RGB;
static const int gl3_tex_alpha_format = GL_RGBA;
extern unsigned gl3_rawpalette[256];
extern unsigned d_8to24table[256];
typedef struct
{
const char *renderer_string;
@ -83,6 +92,19 @@ typedef struct
float max_anisotropy;
} gl3config_t;
typedef struct {
GLuint shaderProgram;
GLint attribPosition;
GLint attribTexCoord;
GLint attribColor;
GLint uniTransMatrix; // TODO: could use 2 or 3 matrices?
// TODO: probably more uniforms, at least gamma and intensity
} gl3ShaderInfo_t;
typedef struct
{
// TODO: what of this do we need?
@ -104,6 +126,12 @@ typedef struct
//enum stereo_modes stereo_mode;
//qboolean hwgamma;
gl3ShaderInfo_t si2D; // shader for rendering 2D with textures
gl3ShaderInfo_t si2Dcolor; // shader for rendering 2D with flat colors
GLuint vbo2D; // this vbo is reused for all 2D drawing (HUD, movies, menu, console, ..)
GLuint vao2D; // same for this vao
} gl3state_t;
extern gl3config_t gl3config;
@ -168,10 +196,19 @@ extern void GL3_Mod_Modellist_f(void);
// gl3_draw.c
extern void GL3_Draw_InitLocal(void);
extern void GL3_Draw_ShutdownLocal(void);
extern gl3image_t * GL3_Draw_FindPic(char *name);
extern void GL3_Draw_GetPicSize(int *w, int *h, char *pic);
extern int GL3_Draw_GetPalette(void);
extern void GL3_Draw_PicScaled(int x, int y, char *pic, float factor);
extern void GL3_Draw_StretchPic(int x, int y, int w, int h, char *pic);
extern void GL3_Draw_CharScaled(int x, int y, int num, float scale);
extern void GL3_Draw_TileClear(int x, int y, int w, int h, char *pic);
extern void GL3_Draw_Fill(int x, int y, int w, int h, int c);
extern void GL3_Draw_FadeScreen(void);
extern void GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data);
// gl3_image.c
extern void GL3_TextureMode(char *string);
extern void GL3_Bind(int texnum);
@ -179,12 +216,19 @@ extern gl3image_t *GL3_LoadPic(char *name, byte *pic, int width, int realwidth,
int height, int realheight, imagetype_t type, int bits);
extern gl3image_t *GL3_FindImage(char *name, imagetype_t type);
extern gl3image_t *GL3_RegisterSkin(char *name);
extern void GL3_ShutdownImages(void);
extern void GL3_FreeUnusedImages(void);
extern void GL3_ImageList_f(void);
// gl3_warp.c
extern void GL3_SetSky(char *name, float rotate, vec3_t axis);
// gl3_shaders.c
extern qboolean GL3_InitShaders(void);
// ############ Cvars ###########
extern cvar_t *gl_msaa_samples;
extern cvar_t *gl_swapinterval;
extern cvar_t *gl_retexturing;