From 69d8af71d6882e801496fcd7ed971081c0b720d8 Mon Sep 17 00:00:00 2001
From: chai <chaifix@163.com>
Date: Sun, 8 Dec 2019 21:29:29 +0800
Subject: *misc

---
 src/core/device.c        | 29 ++++++++++++++++++
 src/core/device.h        | 10 +++++--
 src/core/shader.c        |  6 ++++
 src/core/shader.h        | 12 ++------
 src/core/texture.c       | 78 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/core/texture.h       | 14 ++++-----
 src/core/vert.c          | 16 ----------
 src/core/vert.h          |  6 +---
 src/example/03_texture.c | 24 ++++++++++-----
 src/main.c               | 40 ++++++++++++++++++-------
 src/math/math.h          |  2 ++
 src/math/vec4.c          |  7 +++++
 src/shaders/unlit.c      |  5 ++--
 13 files changed, 188 insertions(+), 61 deletions(-)
 delete mode 100644 src/core/vert.c

diff --git a/src/core/device.c b/src/core/device.c
index 9e4a6eb..cf9fee2 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -43,6 +43,10 @@ struct {
 	Program* program;
 	UniformCollection uniforms;
 
+	/*texture relavent*/
+	FilterMode filtermode;
+	WrapMode wrapmode;
+
 	uint enable;
 
 } state;
@@ -73,6 +77,9 @@ void ssr_init(ssr_Config* conf) {
 	state.buffersize = sizeof(Color) * config.width * config.height;
 	state.zbuffer = ssrM_newvector(uint, config.width * config.height);
 	memset(state.zbuffer, 0xff, sizeof(uint)*config.width*config.height);
+
+	state.filtermode = FILTERMODE_POINT;
+	state.wrapmode = WRAPMODE_CLAMP;
 }
 
 float ssr_getaspect() {
@@ -87,6 +94,22 @@ int ssr_getframebufferh() {
 	return config.height;
 }
 
+void ssr_setfiltermode(FilterMode filter_mode) {
+	state.filtermode = filter_mode;
+}
+
+void ssr_setwrapmode(WrapMode wrap_mode) {
+	state.wrapmode = wrap_mode;
+}
+
+FilterMode ssr_getfiltermode() {
+	return state.filtermode;
+}
+
+WrapMode ssr_getwrapmode() {
+	return state.wrapmode;
+}
+
 void ssr_matrixmode(ssr_MatrixMode mode) {
 	state.matrixmode = mode;
 }
@@ -410,3 +433,9 @@ void ssr_setuniformvec2(uint idx, Vec2* src) {
 	if (idx < 0 || idx > 7) return;
 	state.uniforms.var_vec2[idx] = *src;
 }
+
+void ssr_setuniformtex(uint idx, Texture* tex) {
+	ssr_assert(tex);
+	if (idx < 0 || idx > 11) return;
+	state.uniforms.var_tex[idx] = tex;
+}
diff --git a/src/core/device.h b/src/core/device.h
index 5cf9c4a..b265471 100644
--- a/src/core/device.h
+++ b/src/core/device.h
@@ -39,6 +39,9 @@ float ssr_getaspect();
 int ssr_getframebufferw();
 int ssr_getframebufferh();
 
+void ssr_setfiltermode(FilterMode filter_mode);
+void ssr_setwrapmode(WrapMode wrap_mode);
+
 void ssr_matrixmode(ssr_MatrixMode mode);
 void ssr_loadidentity();
 void ssr_pushmatrix();
@@ -76,6 +79,7 @@ void ssr_setuniformmat4(uint idx, Mat4* src);
 void ssr_setuniformvec4(uint idx, Vec4* src);
 void ssr_setuniformvec3(uint idx, Vec3* src);
 void ssr_setuniformvec2(uint idx, Vec2* src);
+void ssr_setuniformtex(uint idx, Texture* tex);
 
 void ssr_draw(ssr_PrimitiveType primitive);
 void ssr_clearcolor(Color color);
@@ -92,9 +96,9 @@ Color ssr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char
 bool ssr_testdepth(uint x, uint y, uint depth); /*����д����ȣ�����ɻ��Ʒ���true������discard*/
 bool ssr_testdepthf(uint x, uint y, float depth01);
 
-/*
-** Utils
-*/
 void ssrU_viewport(Vec2* p, Vec2* out);
 
+FilterMode ssr_getfiltermode();
+WrapMode ssr_getwrapmode();
+
 #endif
\ No newline at end of file
diff --git a/src/core/shader.c b/src/core/shader.c
index 89daa36..a508820 100644
--- a/src/core/shader.c
+++ b/src/core/shader.c
@@ -215,6 +215,12 @@ void ssrS_setregtofragin(uint extra_varying_flag, FragmentShaderIn* frag_in){
 	}
 }
 
+Color32 texture2d(Texture* tex, Vec2* uv) {
+	FilterMode filter_mode = ssr_getfiltermode();
+	WrapMode wrap_mode = ssr_getwrapmode();
+	return texture_sampling(tex, filter_mode, wrap_mode, uv->x, uv->y);
+}
+
 float* ssrS_bcpnum(Vec3* bc, float A, float B, float C, float* out) {
 	ssr_assert(bc && out);
 	*out = bc->A * A + bc->B * B + bc->C * C;
diff --git a/src/core/shader.h b/src/core/shader.h
index f663a47..bc4e04c 100644
--- a/src/core/shader.h
+++ b/src/core/shader.h
@@ -23,7 +23,7 @@ typedef struct UniformCollection {
 	void* userdata;
 } UniformCollection;
 
-#define TEX(i) (&uniforms->var_tex[i])
+#define TEX(i) (uniforms->var_tex[i])
 #define UM4(i) (&uniforms->var_mat4[i])
 #define UV2(i) (&uniforms->var_vec2[i])
 #define UV3(i) (&uniforms->var_vec3[i])
@@ -157,8 +157,6 @@ Register reg_v2[6];
 Register reg_v3[8];
 Register reg_v4[6];
 
-void reg_all_wipe(); /*���������мĴ���*/
-
 /*�Ĵ���ָ�룬ʹ�ô�����ܻ����Ұָ��*/
 
 float* reg_num_00;
@@ -189,16 +187,12 @@ Vec4* reg_v4_03;
 Vec4* reg_v4_04;
 Vec4* reg_v4_05;
 
-/*���üĴ���ָ�룬ָ��Ĵ�����ע����fragment�׶Σ�ָ���ָ��fragmentIn�ṹ��*/
+/*���üĴ���ָ�룬ָ��Ĵ�������fragment�׶Σ�ָ���ָ��fragmentIn�ṹ��*/
 void ssrS_setupregisterpoints(uint extra_varying_flag, int idx);
 
 /*���üĴ���ָ�룬ָ��fragIn�ṹ*/
 void ssrS_setregtofragin(uint extra_varying_flag, FragmentShaderIn* frag_in);
 
-
-/*
-** texture
-*/
-Color32 texture2d(float x, float y);
+Color32 texture2d(Texture* tex, Vec2* uv);
 
 #endif
\ No newline at end of file
diff --git a/src/core/texture.c b/src/core/texture.c
index 7104bfb..1b70e4b 100644
--- a/src/core/texture.c
+++ b/src/core/texture.c
@@ -1,3 +1,81 @@
 #include "texture.h"
+#define STB_IMAGE_IMPLEMENTATION
+#include "../lib/stb_image.h"
+#include <stdio.h>
 
+static void texture_abgr2argb(Texture* tex) {
+	ssr_assert(tex);
+	int width = tex->width, height = tex->height;
+	Color* pixels = tex->pixels;
+	for (int i = 0; i < width * height; ++i) {
+		uint r = (pixels[i] & 0xff) << 16;
+		uint g = ((pixels[i] >> 8) & 0xff) << 8;
+		uint b = ((pixels[i] >> 16) & 0xff);
+		uint a = ((pixels[i] >> 24) & 0xff) << 24;
+		pixels[i] = r | g | b | a;
+	}
+}
 
+Texture* texture_loadfromfile(const char* path) {
+	ssr_assert(path);
+	FILE* file = fopen(path, "rb");
+	ssr_assert(file);
+	fseek(file, 0, SEEK_END);
+	int size = ftell(file);
+	fseek(file, 0, SEEK_SET);
+	char* buffer = ssrM_newvector(char, size);
+	ssr_assert(buffer);
+	int l = fread(buffer, 1, size, file);
+	if ( l!= size) {
+		free(buffer);
+		fclose(file);
+		return NULL;
+	}
+	fclose(file);
+	int width, height;
+	Color* pixels = (Color*)stbi_load_from_memory((unsigned char*)buffer, size, &width, &height, NULL, STBI_rgb_alpha);
+	ssrM_free(buffer);
+	if (!pixels) return NULL;
+	Texture* texture = ssrM_new(Texture);
+	texture->width = width; texture->height = height;
+	texture->pixels = pixels;
+	texture_abgr2argb(texture);
+	return texture;
+}
+
+static Color32 sampling(Texture* tex, WrapMode wrap_mode, int x, int y) {
+	Color32 color; 
+	if (wrap_mode == WRAPMODE_CLAMP) { /*clamp*/
+		x = clamp(x, 0, tex->width - 1);
+		y = clamp(y, 0, tex->height - 1);
+	}	else { /*repeat*/
+		x = x % tex->width; 
+		y = y % tex->height;
+	}
+	color_tocolor32(tex->pixels[x + y * tex->width], &color);
+	return color;
+}
+
+Color32 texture_sampling(Texture* tex, FilterMode filter_mode, WrapMode wrap_mode, float x01, float y01) {
+	ssr_assert(tex);
+	int x = x01 * tex->width, y = (1 - y01) * tex->height; /*map to texture coordinate*/
+	if (filter_mode == FILTERMODE_POINT) {
+		return sampling(tex, wrap_mode, x, y);
+	}
+	else if (filter_mode == FILTERMODE_BILINEAR) {
+		int x_min = floor(x), y_min = floor(y);
+		int x_max = ceil(x), y_max = ceil(y);
+		static Color32 tl, tr, bl, br, t, b, out;
+		tl = sampling(tex, wrap_mode, x_min, y_min);
+		tr = sampling(tex, wrap_mode, x_max, y_min);
+		bl = sampling(tex, wrap_mode, x_min, y_max);
+		br = sampling(tex, wrap_mode, x_max, y_max);
+		vec4_lerp(&tl, &tr, x - x_min, &t);
+		vec4_lerp(&bl, &br, x - x_min, &b);
+		vec4_lerp(&t, &b, y - y_min, &out);
+		return out;
+	}
+	else if (filter_mode == FILTERMODE_TRILINEAR) {
+		/*TODO*/
+	}
+}
diff --git a/src/core/texture.h b/src/core/texture.h
index 20a0228..49fed4b 100644
--- a/src/core/texture.h
+++ b/src/core/texture.h
@@ -3,13 +3,6 @@
 
 #include "vert.h"
 
-typedef struct Texture{
-	uint width, height;
-	Color* pixels;
-}Texture;
-
-void texture_loadfromfile(const char* path, Texture* out);
-
 typedef enum FilterMode {
 	FILTERMODE_POINT, 
 	FILTERMODE_BILINEAR,
@@ -21,6 +14,13 @@ typedef enum WrapMode{
 	WRAPMODE_CLAMP,
 } WrapMode;
 
+typedef struct Texture{
+	uint width, height;
+	Color* pixels;
+}Texture;
+
+Texture* texture_loadfromfile(const char* path);
+
 Color32 texture_sampling(Texture* tex, FilterMode filter_mode, WrapMode wrap_mode, float x, float y);
 
 #endif
\ No newline at end of file
diff --git a/src/core/vert.c b/src/core/vert.c
deleted file mode 100644
index 95469d3..0000000
--- a/src/core/vert.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "vert.h"
-
-Vert* vert_new() {
-	Vert* vert = ssrM_new(Vert);
-	return vert;
-}
-
-void vert_init(Vert* v) {
-	ssr_assert(v);
-	v->index = 0;
-}
-
-void vert_free(Vert* v) {
-	ssr_assert(v);
-	ssrM_free(v);
-}
\ No newline at end of file
diff --git a/src/core/vert.h b/src/core/vert.h
index 0542ded..a85e38c 100644
--- a/src/core/vert.h
+++ b/src/core/vert.h
@@ -22,7 +22,7 @@ void color32_saturate(Color32* c);
 
 /*readonly*/
 typedef struct Vert {
-	int index;
+	uint index;
 	Vec3 position;
 	Vec3 normal;
 	Vec3 tangent;
@@ -32,8 +32,4 @@ typedef struct Vert {
 	Vec4 weight;
 } Vert;
 
-Vert* vert_new(uint comp);
-void vert_init(Vert* v, uint comp); 
-void vert_free(Vert* v); 
-
 #endif
\ No newline at end of file
diff --git a/src/example/03_texture.c b/src/example/03_texture.c
index acb85c4..d4e08a4 100644
--- a/src/example/03_texture.c
+++ b/src/example/03_texture.c
@@ -10,20 +10,22 @@ static int cube[] = {
 };
 
 static Vert verts[] = {
-	{0, {1, 1, 1}, {1, 1, 1}, zerovec3, zerovec2, 0xffff0000},
-	{1, {-1, 1, 1}, {-1, 1, 1}, zerovec3, zerovec2,0xff00ff00},
-	{2, {-1, -1, 1}, {-1, -1, 1}, zerovec3, zerovec2, 0xff0000ff},
-	{3, {1, -1, 1}, {1, -1, 1}, zerovec3, zerovec2, 0xffff00ff},
-	{4, {1, 1, -1}, {1, 1, -1}, zerovec3, zerovec2, 0xffaa28aa},
-	{5, {-1, 1, -1}, {-1, 1, -1}, zerovec3, zerovec2,0xffFFC58E},
-	{6, {-1, -1, -1}, {-1, -1, -1}, zerovec3, zerovec2, 0xffA100FF},
-	{7, {1, -1, -1}, {1, -1, -1}, zerovec3, zerovec2, 0xffFAFF00},
+	{0, {1, 1, 1}, {1, 1, 1}, zerovec3, {1, 1}, 0xffff0000},
+	{1, {-1, 1, 1}, {-1, 1, 1}, zerovec3, {0, 1},0xff00ff00},
+	{2, {-1, -1, 1}, {-1, -1, 1}, zerovec3, {0, 0}, 0xff0000ff},
+	{3, {1, -1, 1}, {1, -1, 1}, zerovec3, {1, 0}, 0xffff00ff},
+	{4, {1, 1, -1}, {1, 1, -1}, zerovec3, {1, 0} , 0xffaa28aa},
+	{5, {-1, 1, -1}, {-1, 1, -1}, zerovec3, {0, 0},0xffFFC58E},
+	{6, {-1, -1, -1}, {-1, -1, -1}, zerovec3, {0, 1}, 0xffA100FF},
+	{7, {1, -1, -1}, {1, -1, -1}, zerovec3, {1, 1} , 0xffFAFF00},
 };
 
 extern Program ssr_built_in_shader_unlit;
 
 static Vec3 light = {-1, -1, -1};
 
+static Texture* texture;
+
 void onloadtexture(void* data) {
 	ssr_matrixmode(MATRIX_PROJECTION);
 	ssr_loadidentity();
@@ -38,6 +40,12 @@ void onloadtexture(void* data) {
 	ssr_useprogram(&ssr_built_in_shader_unlit);
 	ssr_enable(ENABLEMASK_BACKFACECULL);
 	ssr_enable(ENABLEMASK_DEPTHTEST);
+
+	texture = texture_loadfromfile("res/helmet/screenshot2.png");
+	ssr_setuniformtex(0, texture);
+
+	ssr_setwrapmode(WRAPMODE_CLAMP);
+	ssr_setfiltermode(FILTERMODE_POINT);
 }
 
 void oneventtexture(void* data) {
diff --git a/src/main.c b/src/main.c
index 1dd4663..176c2e6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,8 +8,8 @@
 
 SDL_Surface* suf;
 
-#define SCREEN_WIDTH 600 /*800*/
-#define SCREEN_HEIGHT 500 /*600*/
+#define SCREEN_WIDTH 600/*800*/
+#define SCREEN_HEIGHT 480/*600*/
 
 typedef void(*F)(void*);
 F onload;
@@ -30,7 +30,7 @@ SETEXAMPLEF(onupdate, i)
 
 int main(int argc, char* argv[])
 {
-	if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
+	if (SDL_Init(SDL_INIT_EVENTS | SDL_INIT_TIMER | SDL_INIT_VIDEO) < 0)
 		return 1;
 	SDL_Window* wnd = SDL_CreateWindow("Soft Shade Room", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
 	SDL_Event e;
@@ -40,18 +40,24 @@ int main(int argc, char* argv[])
 	ssr_assert(suf->format->Rshift == 16);
 	ssr_assert(suf->format->Gshift == 8);
 	ssr_assert(suf->format->Bshift == 0);
+
 	/* init ssr */
 	ssr_Config config = {
-		SCREEN_WIDTH, SCREEN_HEIGHT,/* screen size */
-		0, /* double buffer */
-		suf->pixels /* screen buffer */ 
+		SCREEN_WIDTH, SCREEN_HEIGHT,
+		0,
+		suf->pixels
 	};
 	ssr_init(&config);
+
 	SETEXAMPLE(EXAMPLECUR);
+
 	onload(0);
+
 	/* main loop */
-	uint previous = SDL_GetTicks();
+	uint prev = SDL_GetTicks();
 	uint dt = 0;
+	uint frame_count = 0;
+	uint time_stamp = 0;
 	while (1) {
 		while (SDL_PollEvent(&e)) {
 			if (e.type == SDL_QUIT) {
@@ -60,15 +66,27 @@ int main(int argc, char* argv[])
 				onevent(&e);
 			}
 		}
-		dt = SDL_GetTicks() - previous;
-		previous = dt + previous;
+
+		dt = SDL_GetTicks() - prev;
+		prev += dt;
+		time_stamp += dt;
+		++frame_count;
+		if (time_stamp >= 1000) {
+			printf("%3d fps\n", frame_count);
+			time_stamp -= 1000;
+			frame_count = 0;
+		}
+
 		onupdate(&dt);
 		ondraw(0);
 		ssr_present();
 		SDL_UpdateWindowSurface(wnd);
-		Sleep(10); /*100fps limit*/
+		
+		Sleep(1); /*reduce cpu usage*/
 	}
-	quit:
+
+quit:
 	SDL_Quit();
+
 	return 0;
 }
diff --git a/src/math/math.h b/src/math/math.h
index 35219a3..1db7df7 100644
--- a/src/math/math.h
+++ b/src/math/math.h
@@ -182,6 +182,8 @@ void vec4_dividew(Vec4* v, Vec3* out);
 void vec4_tostring(Vec4* v, char buf[]);
 void vec4_print(Vec4* v);
 
+void vec4_lerp(Vec4* a, Vec4* b, float t, Vec4* out);
+
 /************************************************************************/
 /* Matrix                                                               */
 /************************************************************************/
diff --git a/src/math/vec4.c b/src/math/vec4.c
index ca64820..b79adca 100644
--- a/src/math/vec4.c
+++ b/src/math/vec4.c
@@ -21,4 +21,11 @@ void vec4_tostring(Vec4* v, char buf[]) {
 void vec4_print(Vec4* v) {
 	vec4_tostring(v, printbuffer);
 	printf("\n%s\n", printbuffer);
+}
+
+void vec4_lerp(Vec4* a, Vec4* b, float t, Vec4* out) {
+	out->x = lerp(a->x, b->x, t);
+	out->y = lerp(a->y, b->y, t);
+	out->z = lerp(a->z, b->z, t);
+	out->w = lerp(a->w, b->w, t);
 }
\ No newline at end of file
diff --git a/src/shaders/unlit.c b/src/shaders/unlit.c
index 7ff4497..fe692f0 100644
--- a/src/shaders/unlit.c
+++ b/src/shaders/unlit.c
@@ -17,11 +17,12 @@ static bool frag(UniformCollection* uniforms, FragmentShaderIn* in, Color* color
 	float strongness = vec3_dot(light, &in->normal);
 	vec3_scale(vert_color, 1 - clamp(strongness, 0, 1), vert_color);
 	*color = color32_tocolor(vert_color);
-	
+  //Color32 c = texture2d(maintex, &in->texcoord);
+  //*color = color32_tocolor(&c);
 	return 1;
 }
 
 Program ssr_built_in_shader_unlit = { 
 	vert, frag,
-	VARYING_V4_00
+	VARYING_V4_00 | VARYING_TEXCOORD
 };
-- 
cgit v1.1-26-g67d0