diff --git a/engine/include/GearBox/Foundation.h b/engine/include/GearBox/Foundation.h index b6642b3..a4762b0 100644 --- a/engine/include/GearBox/Foundation.h +++ b/engine/include/GearBox/Foundation.h @@ -14,5 +14,6 @@ #include #include #include +#include #endif diff --git a/engine/include/GearBox/GL.h b/engine/include/GearBox/GL.h index 4439810..ced75b8 100644 --- a/engine/include/GearBox/GL.h +++ b/engine/include/GearBox/GL.h @@ -10,11 +10,16 @@ extern "C" { #endif +#define GBGLMaxDistance 100.0 + /* gl_shader.c */ GBDECL int GBGLShaderPrepare(GBGL gl, GLuint* shader, const char* vs, const char* fs); /* gl_texture.c */ -GBDECL int GBGLTexturePrepare(GBGL gl, GLuint* texture, unsigned char* rgba, int width, int height); +GBDECL void GBGLTexturePrepare(GBGL gl, GLuint* texture, unsigned char* rgba, int width, int height); +GBDECL void GBGLTextureSet(GBGL gl, GLuint texture); +GBDECL int GBGLTextureLoadFile(GBGL gl, GLuint* texture, int* width, int* height, const char* filename); +GBDECL void GBGLTextureDelete(GBGL gl, GLuint texture); /* gl_shadow.c */ GBDECL void GBGLShadowInit(GBGL gl); @@ -32,6 +37,7 @@ GBDECL void GBGLClear(GBGL gl); GBDECL void GBGLIgnoreDepth(GBGL gl); GBDECL void GBGLCareDepth(GBGL gl); GBDECL void GBGLSetLight(GBGL gl); +GBDECL void GBGLPolygon(GBGL gl, int pairs, GBVector3* vert, GBVector2* tex); /* gl_camera.c */ GBDECL void GBGLCameraPerspective(GBGL gl, GBNumber width, GBNumber height); diff --git a/engine/include/GearBox/SkyBox.h b/engine/include/GearBox/SkyBox.h new file mode 100644 index 0000000..bc7a139 --- /dev/null +++ b/engine/include/GearBox/SkyBox.h @@ -0,0 +1,19 @@ +#ifndef __GEARBOX_SKYBOX_H__ +#define __GEARBOX_SKYBOX_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +GBDECL GBSkyBox GBSkyBoxOpen(GBClient client, const char* base); +GBDECL void GBSkyBoxDraw(GBSkyBox skybox); +GBDECL void GBSkyBoxClose(GBSkyBox skybox); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/engine/include/GearBox/String.h b/engine/include/GearBox/String.h index 3ae0026..acfda3a 100644 --- a/engine/include/GearBox/String.h +++ b/engine/include/GearBox/String.h @@ -9,6 +9,7 @@ extern "C" { #endif GBDECL char* GBStringDuplicate(const char* str); +GBDECL char* GBStringConcat(const char* str1, const char* str2); #ifdef __cplusplus } diff --git a/engine/include/GearBox/TypeDefs.h b/engine/include/GearBox/TypeDefs.h index bea0574..65b6b88 100644 --- a/engine/include/GearBox/TypeDefs.h +++ b/engine/include/GearBox/TypeDefs.h @@ -47,6 +47,7 @@ typedef struct _GBEngine* GBEngine; typedef struct _GBFile* GBFile; typedef struct _GBResource* GBResource; typedef struct _GBGL* GBGL; +typedef struct _GBSkyBox* GBSkyBox; #else typedef void* GBClient; typedef void* GBServer; @@ -54,8 +55,10 @@ typedef void* GBEngine; typedef void* GBFile; typedef void* GBResource; typedef void* GBGL; +typedef void* GBSkyBox; #endif typedef float GBNumber; +typedef GBNumber GBVector2[2]; typedef GBNumber GBVector3[3]; typedef GBNumber GBVector4[4]; typedef GBNumber GBMatrix4x4[16]; @@ -93,6 +96,18 @@ struct _GBClient { GBVector3 look_at; GBVector3 camera; GBVector4 light0; + GBSkyBox skybox; +}; + +struct _GBSkyBox { + GBEngine engine; + + GLuint left; + GLuint right; + GLuint front; + GLuint back; + GLuint up; + GLuint down; }; struct _GBServer { diff --git a/engine/resource/shader/shadow.fs b/engine/resource/shader/shadow.fs index dfe14c9..e5d9e9e 100644 --- a/engine/resource/shader/shadow.fs +++ b/engine/resource/shader/shadow.fs @@ -3,6 +3,7 @@ varying vec4 vPos; varying vec3 vNrm; varying vec4 vShadowCoord; +varying vec4 vColor; uniform sampler2D depth_texture; uniform sampler2D current_texture; @@ -62,11 +63,11 @@ float ShadowCoef(void){ } void main(void){ - vec4 c = enable_lighting > 0.5 ? PhongShading() : gl_Color; + vec4 c = enable_lighting > 0.5 ? PhongShading() : vColor; vec4 ambient = gl_LightSource[0].ambient; float shadow_coef = ShadowCoef(); - //c = c * texture2D(current_texture, gl_TexCoord[0].st); + c = c * texture2D(current_texture, gl_TexCoord[0].st); gl_FragColor = ambient * shadow_coef * c + (1.0 - ambient) * c; gl_FragColor.a = 1.0; diff --git a/engine/resource/shader/shadow.vs b/engine/resource/shader/shadow.vs index 659d2c7..e423e47 100644 --- a/engine/resource/shader/shadow.vs +++ b/engine/resource/shader/shadow.vs @@ -3,12 +3,15 @@ varying vec4 vPos; varying vec3 vNrm; varying vec4 vShadowCoord; +varying vec4 vColor; void main(void){ vPos = gl_ModelViewMatrix * gl_Vertex; vNrm = normalize(gl_NormalMatrix * gl_Normal); vShadowCoord = gl_TextureMatrix[7] * gl_ModelViewMatrix * gl_Vertex; + vColor = gl_Color; + gl_Position = gl_ProjectionMatrix * vPos; gl_FrontColor = gl_Color; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; diff --git a/engine/resource/skybox/back.png b/engine/resource/skybox/back.png new file mode 100644 index 0000000..936851b Binary files /dev/null and b/engine/resource/skybox/back.png differ diff --git a/engine/resource/skybox/down.png b/engine/resource/skybox/down.png new file mode 100644 index 0000000..d7e46fa Binary files /dev/null and b/engine/resource/skybox/down.png differ diff --git a/engine/resource/skybox/front.png b/engine/resource/skybox/front.png new file mode 100644 index 0000000..17309bd Binary files /dev/null and b/engine/resource/skybox/front.png differ diff --git a/engine/resource/skybox/left.png b/engine/resource/skybox/left.png new file mode 100644 index 0000000..046dd0a Binary files /dev/null and b/engine/resource/skybox/left.png differ diff --git a/engine/resource/skybox/right.png b/engine/resource/skybox/right.png new file mode 100644 index 0000000..9fffb8c Binary files /dev/null and b/engine/resource/skybox/right.png differ diff --git a/engine/resource/skybox/up.png b/engine/resource/skybox/up.png new file mode 100644 index 0000000..871e405 Binary files /dev/null and b/engine/resource/skybox/up.png differ diff --git a/engine/src/client.c b/engine/src/client.c index 9bbfabc..1910b81 100644 --- a/engine/src/client.c +++ b/engine/src/client.c @@ -2,6 +2,7 @@ #include #include +#include #include GBClient GBClientCreate(GBEngine engine) { @@ -11,12 +12,12 @@ GBClient GBClientCreate(GBEngine engine) { client->engine = engine; - client->camera[0] = 5; - client->camera[1] = 5; - client->camera[2] = 5; + client->camera[0] = 0; + client->camera[1] = 0; + client->camera[2] = 0; client->look_at[0] = 0; - client->look_at[1] = 0; + client->look_at[1] = 1; client->look_at[2] = 0; client->light0[0] = 5; @@ -26,6 +27,8 @@ GBClient GBClientCreate(GBEngine engine) { client->gl = GBGLCreate(client); + client->skybox = GBSkyBoxOpen(client, "base:/skybox"); + GBLog(GBLogInfo, "Created client"); return client; @@ -39,8 +42,6 @@ void GBClientDestroy(GBClient client) { GBLog(GBLogInfo, "Destroyed client"); } -static double r = 0; - static void scene(GBClient client) { } @@ -54,13 +55,16 @@ void GBClientStep(GBClient client) { GBGLShadowAfterMapping(client->gl); } + if(client->skybox != NULL) GBSkyBoxDraw(client->skybox); scene(client); GBGLShadowEnd(client->gl); client->engine->param->gl_swapbuffer(); - client->camera[0] = cos(r) * 5; - client->camera[2] = sin(r) * 5; + static double r = 0; + + client->look_at[0] = cos(r) * 5; + client->look_at[2] = sin(r) * 5; r += 0.1; } diff --git a/engine/src/gl.c b/engine/src/gl.c index c3cc383..4975225 100644 --- a/engine/src/gl.c +++ b/engine/src/gl.c @@ -60,3 +60,14 @@ void GBGLSetLight(GBGL gl) { glLightfv(GL_LIGHT0, GL_POSITION, f); } + +void GBGLPolygon(GBGL gl, int pairs, GBVector3* vert, GBVector2* tex) { + int i; + + glBegin(GL_POLYGON); + for(i = 0; i < pairs; i++) { + if(tex != NULL) glTexCoord2f(tex[i][0], tex[i][1]); + glVertex3f(vert[i][0], vert[i][1], vert[i][2]); + } + glEnd(); +} diff --git a/engine/src/gl_camera.c b/engine/src/gl_camera.c index 7e1d358..33e2455 100644 --- a/engine/src/gl_camera.c +++ b/engine/src/gl_camera.c @@ -9,7 +9,7 @@ void GBGLCameraPerspective(GBGL gl, GBNumber width, GBNumber height) { int i; GBNumber fovy = 60.0; GBNumber znear = 0.01; - GBNumber zfar = 100.0; + GBNumber zfar = GBGLMaxDistance; aspect = width / height; f = GBMathCot(fovy / 180 * GBMathPi / 2); diff --git a/engine/src/gl_texture.c b/engine/src/gl_texture.c index 6edc89f..dcdf07c 100644 --- a/engine/src/gl_texture.c +++ b/engine/src/gl_texture.c @@ -1,6 +1,29 @@ #include -int GBGLTexturePrepare(GBGL gl, GLuint* texture, unsigned char* rgba, int width, int height) { +#include + +#include + +void GBGLTexturePrepare(GBGL gl, GLuint* texture, unsigned char* rgba, int width, int height) { + int y; + + /* image gets flipped here... because opengl coord system is quite confusing */ + for(y = 0; y < height / 2; y++) { + int x; + for(x = 0; x < width; x++) { + int p; + for(p = 0; p < 4; p++) { + unsigned char* s1 = &rgba[(y * width + x) * 4 + p]; + unsigned char* s2 = &rgba[((height - 1 - y) * width + x) * 4 + p]; + unsigned char p1 = *s1; + unsigned char p2 = *s2; + + *s2 = p1; + *s1 = p2; + } + } + } + glGenTextures(1, texture); glBindTexture(GL_TEXTURE_2D, *texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba); @@ -18,3 +41,48 @@ void GBGLTextureDisable(GBGL gl, GLuint texture) { glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); } + +int GBGLTextureLoadFile(GBGL gl, GLuint* texture, int* width, int* height, const char* filename) { + GBFile f = GBFileOpen(gl->engine, filename); + unsigned char* data; + unsigned char* rgba; + unsigned long sz; + int ch; + int st = 1; + int w, h; + if(f == NULL) return 0; + + sz = GBFileSize(f); + + data = malloc(sz); + GBFileRead(f, data, sz); + GBFileClose(f); + + if((rgba = stbi_load_from_memory(data, sz, &w, &h, &ch, 4)) == NULL) { + st = 0; + } else { + GBGLTexturePrepare(gl, texture, rgba, w, h); + + free(rgba); + } + + if(width != NULL) *width = w; + if(height != NULL) *height = h; + + free(data); + + return st; +} + +void GBGLTextureSet(GBGL gl, GLuint texture) { + glBindTexture(GL_TEXTURE_2D, texture); + if(texture == 0) { + glDisable(GL_TEXTURE_2D); + } else { + glEnable(GL_TEXTURE_2D); + } +} + +void GBGLTextureDelete(GBGL gl, GLuint texture) { + glDeleteTextures(1, &texture); +} diff --git a/engine/src/skybox.c b/engine/src/skybox.c new file mode 100644 index 0000000..e3a2203 --- /dev/null +++ b/engine/src/skybox.c @@ -0,0 +1,129 @@ +#include + +#include +#include + +GBSkyBox GBSkyBoxOpen(GBClient client, const char* base) { + GBSkyBox skybox = malloc(sizeof(*skybox)); + char* p; + void* ptr[12]; + int i; + + memset(skybox, 0, sizeof(*skybox)); + + skybox->engine = client->engine; + + ptr[0] = &skybox->left; + ptr[1] = "/left.png"; + ptr[2] = &skybox->right; + ptr[3] = "/right.png"; + ptr[4] = &skybox->front; + ptr[5] = "/front.png"; + ptr[6] = &skybox->back; + ptr[7] = "/back.png"; + ptr[8] = &skybox->up; + ptr[9] = "/up.png"; + ptr[10] = &skybox->down; + ptr[11] = "/down.png"; + + for(i = 0; i < 12; i += 2) { + p = GBStringConcat(base, ptr[i + 1]); + if(!GBGLTextureLoadFile(client->gl, ptr[i], NULL, NULL, p)) { + free(p); + GBSkyBoxClose(skybox); + return NULL; + } + free(p); + } + + return skybox; +} + +void GBSkyBoxDraw(GBSkyBox skybox) { + GBGL gl = skybox->engine->client->gl; + int i; + GBVector3 v[4]; + GBVector2 t[4]; + GBNumber s = 0.0001; + + t[0][0] = 0, t[0][1] = 1; + + t[1][0] = 0, t[1][1] = 0; + + t[2][0] = 1, t[2][1] = 0; + + t[3][0] = 1, t[3][1] = 1; + + GBGLIgnoreDepth(gl); + GBGLShadowDisable(gl); + + for(i = 0; i < 6; i++) { + GLuint tex; + int j, k; + + if(i == 0) { + tex = skybox->front; + + v[0][0] = -1 - s, v[0][1] = 1 + s, v[0][2] = -1; + v[1][0] = -1 - s, v[1][1] = -1 - s, v[1][2] = -1; + v[2][0] = 1 + s, v[2][1] = -1 - s, v[2][2] = -1; + v[3][0] = 1 + s, v[3][1] = 1 + s, v[3][2] = -1; + } else if(i == 1) { + tex = skybox->back; + + v[0][0] = 1 + s, v[0][1] = 1 + s, v[0][2] = 1; + v[1][0] = 1 + s, v[1][1] = -1 - s, v[1][2] = 1; + v[2][0] = -1 - s, v[2][1] = -1 - s, v[2][2] = 1; + v[3][0] = -1 - s, v[3][1] = 1 + s, v[3][2] = 1; + } else if(i == 2) { + tex = skybox->left; + + v[0][0] = -1, v[0][1] = 1 + s, v[0][2] = 1 + s; + v[1][0] = -1, v[1][1] = -1 - s, v[1][2] = 1 + s; + v[2][0] = -1, v[2][1] = -1 - s, v[2][2] = -1 - s; + v[3][0] = -1, v[3][1] = 1 + s, v[3][2] = -1 - s; + } else if(i == 3) { + tex = skybox->right; + + v[0][0] = 1, v[0][1] = 1 + s, v[0][2] = -1 - s; + v[1][0] = 1, v[1][1] = -1 - s, v[1][2] = -1 - s; + v[2][0] = 1, v[2][1] = -1 - s, v[2][2] = 1 + s; + v[3][0] = 1, v[3][1] = 1 + s, v[3][2] = 1 + s; + } else if(i == 4) { + tex = skybox->up; + + v[0][0] = -1 - s, v[0][1] = 1, v[0][2] = 1 + s; + v[1][0] = -1 - s, v[1][1] = 1, v[1][2] = -1 - s; + v[2][0] = 1 + s, v[2][1] = 1, v[2][2] = -1 - s; + v[3][0] = 1 + s, v[3][1] = 1, v[3][2] = 1 + s; + } else if(i == 5) { + tex = skybox->down; + + v[0][0] = -1 - s, v[0][1] = -1, v[0][2] = -1 - s; + v[1][0] = -1 - s, v[1][1] = -1, v[1][2] = 1 + s; + v[2][0] = 1 + s, v[2][1] = -1, v[2][2] = 1 + s; + v[3][0] = 1 + s, v[3][1] = -1, v[3][2] = -1 - s; + } + + for(j = 0; j < 4; j++) { + for(k = 0; k < 3; k++) { + v[j][k] *= GBGLMaxDistance / 2; + v[j][k] += gl->engine->client->camera[k]; + } + } + + GBGLTextureSet(gl, tex); + + GBGLPolygon(gl, 4, v, t); + } + + GBGLTextureSet(gl, 0); + + GBGLShadowEnable(gl); + GBGLCareDepth(gl); +} + +void GBSkyBoxClose(GBSkyBox skybox) { + if(skybox->left > 0) GBGLTextureDelete(skybox->engine->client->gl, skybox->left); + free(skybox); +} diff --git a/engine/src/stb_image.c b/engine/src/stb_image.c new file mode 100644 index 0000000..9177288 --- /dev/null +++ b/engine/src/stb_image.c @@ -0,0 +1,2 @@ +#define STB_IMAGE_IMPLEMENTATION +#include diff --git a/engine/src/string.c b/engine/src/string.c index eee6b26..26aec80 100644 --- a/engine/src/string.c +++ b/engine/src/string.c @@ -7,3 +7,12 @@ char* GBStringDuplicate(const char* str) { return s; } + +char* GBStringConcat(const char* str1, const char* str2) { + char* r = malloc(strlen(str1) + strlen(str2) + 1); + + strcpy(r, str1); + strcat(r, str2); + + return r; +}