mirror of
https://github.com/haya3218/SDfmL.git
synced 2024-08-14 23:57:09 +00:00
*very* experimental shader support
havent tested it yet, beware
This commit is contained in:
parent
e4dc4a8331
commit
d2be0d9e2b
3 changed files with 221 additions and 2 deletions
|
@ -35,6 +35,7 @@
|
||||||
#include "guicon.h"
|
#include "guicon.h"
|
||||||
|
|
||||||
#include "sdfml/music.hpp"
|
#include "sdfml/music.hpp"
|
||||||
|
#include "sdfml/shader.hpp"
|
||||||
|
|
||||||
#include "SDL_gpu/SDL_gpu.h"
|
#include "SDL_gpu/SDL_gpu.h"
|
||||||
|
|
||||||
|
@ -100,6 +101,8 @@ inline std::string _GetCurrentDirectory()
|
||||||
|
|
||||||
namespace sdfml {
|
namespace sdfml {
|
||||||
|
|
||||||
|
static double elapsed;
|
||||||
|
|
||||||
inline int llog(string prefix, string msg, lLOG_TYPE type = NORMAL, string file = "???.cpp", int line = 0) {
|
inline int llog(string prefix, string msg, lLOG_TYPE type = NORMAL, string file = "???.cpp", int line = 0) {
|
||||||
clock_t now = std::clock();
|
clock_t now = std::clock();
|
||||||
|
|
||||||
|
@ -187,6 +190,8 @@ namespace sdfml {
|
||||||
|
|
||||||
Vector3<Uint8> color;
|
Vector3<Uint8> color;
|
||||||
|
|
||||||
|
ShaderProg shader;
|
||||||
|
|
||||||
virtual void create(int x, int y, string path) {
|
virtual void create(int x, int y, string path) {
|
||||||
this->x = x;
|
this->x = x;
|
||||||
this->y = y;
|
this->y = y;
|
||||||
|
@ -198,6 +203,9 @@ namespace sdfml {
|
||||||
color.g = 255;
|
color.g = 255;
|
||||||
color.b = 255;
|
color.b = 255;
|
||||||
}
|
}
|
||||||
|
virtual void addShader(std::string path) {
|
||||||
|
shader.loadShader(path, FRAGMENT, mContext.gpu_render, _tex_gpu);
|
||||||
|
}
|
||||||
GPU_Rect *r;
|
GPU_Rect *r;
|
||||||
virtual void update(float elapsed) {
|
virtual void update(float elapsed) {
|
||||||
_x = x+offset.x;
|
_x = x+offset.x;
|
||||||
|
@ -206,14 +214,17 @@ namespace sdfml {
|
||||||
r = &_src_rect;
|
r = &_src_rect;
|
||||||
if (r->w == 0)
|
if (r->w == 0)
|
||||||
r = NULL;
|
r = NULL;
|
||||||
|
shader.updateShader(static_cast<float>(sdfml::elapsed));
|
||||||
GPU_Rect dst = {static_cast<float>(_x-_camera->x), static_cast<float>(_y-_camera->y), width*scale.x, height*scale.y};
|
GPU_Rect dst = {static_cast<float>(_x-_camera->x), static_cast<float>(_y-_camera->y), width*scale.x, height*scale.y};
|
||||||
GPU_BlitRectX(_tex_gpu, r, mContext.gpu_render, &dst, angle, NULL, NULL, GPU_FLIP_NONE);
|
GPU_BlitRectX(_tex_gpu, r, mContext.gpu_render, &dst, angle, NULL, NULL, GPU_FLIP_NONE);
|
||||||
|
shader.postUpdate();
|
||||||
}
|
}
|
||||||
virtual void destroy() {
|
virtual void destroy() {
|
||||||
_x = 0;
|
_x = 0;
|
||||||
_y = 0;
|
_y = 0;
|
||||||
_w = 0;
|
_w = 0;
|
||||||
_h = 0;
|
_h = 0;
|
||||||
|
shader.freeShader();
|
||||||
GPU_FreeImage(_tex_gpu);
|
GPU_FreeImage(_tex_gpu);
|
||||||
}
|
}
|
||||||
virtual void updateCamera(SDL_Rect* camera) {
|
virtual void updateCamera(SDL_Rect* camera) {
|
||||||
|
@ -466,8 +477,6 @@ namespace sdfml {
|
||||||
return FRAMERATE*time;
|
return FRAMERATE*time;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double elapsed;
|
|
||||||
|
|
||||||
inline int update() {
|
inline int update() {
|
||||||
int lastUpdate = SDL_GetTicks();
|
int lastUpdate = SDL_GetTicks();
|
||||||
bool run = true;
|
bool run = true;
|
||||||
|
|
179
src/sdfml/shader.cpp
Normal file
179
src/sdfml/shader.cpp
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
#include "shader.hpp"
|
||||||
|
|
||||||
|
// Loads a shader and prepends version/compatibility info before compiling it.
|
||||||
|
// Normally, you can just use GPU_LoadShader() for shader source files or GPU_CompileShader() for strings.
|
||||||
|
// However, some hardware (certain ATI/AMD cards) does not let you put non-#version preprocessing at the top of the file.
|
||||||
|
// Therefore, I need to prepend the version info here so I can support both GLSL and GLSLES with one shader file.
|
||||||
|
Uint32 loadShaderFromFile(GPU_ShaderEnum shader_type, const char* filename)
|
||||||
|
{
|
||||||
|
SDL_RWops* rwops;
|
||||||
|
Uint32 shader;
|
||||||
|
char* source;
|
||||||
|
int header_size, file_size;
|
||||||
|
const char* header = "";
|
||||||
|
GPU_Renderer* renderer = GPU_GetCurrentRenderer();
|
||||||
|
|
||||||
|
// Open file
|
||||||
|
rwops = SDL_RWFromFile(filename, "rb");
|
||||||
|
if(rwops == NULL)
|
||||||
|
{
|
||||||
|
GPU_PushErrorCode("load_shader", GPU_ERROR_FILE_NOT_FOUND, "Shader file \"%s\" not found", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get file size
|
||||||
|
file_size = SDL_RWseek(rwops, 0, SEEK_END);
|
||||||
|
SDL_RWseek(rwops, 0, SEEK_SET);
|
||||||
|
|
||||||
|
// Get size from header
|
||||||
|
if(renderer->shader_language == GPU_LANGUAGE_GLSL)
|
||||||
|
{
|
||||||
|
if(renderer->max_shader_version >= 120)
|
||||||
|
header = "#version 120\n";
|
||||||
|
else
|
||||||
|
header = "#version 110\n"; // Maybe this is good enough?
|
||||||
|
}
|
||||||
|
else if(renderer->shader_language == GPU_LANGUAGE_GLSLES)
|
||||||
|
header = "#version 100\nprecision mediump int;\nprecision mediump float;\n";
|
||||||
|
|
||||||
|
header_size = strlen(header);
|
||||||
|
|
||||||
|
// Allocate source buffer
|
||||||
|
source = (char*)malloc(sizeof(char)*(header_size + file_size + 1));
|
||||||
|
|
||||||
|
// Prepend header
|
||||||
|
strcpy(source, header);
|
||||||
|
|
||||||
|
// Read in source code
|
||||||
|
SDL_RWread(rwops, source + strlen(source), 1, file_size);
|
||||||
|
source[header_size + file_size] = '\0';
|
||||||
|
|
||||||
|
// Compile the shader
|
||||||
|
shader = GPU_CompileShader(shader_type, source);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
free(source);
|
||||||
|
SDL_RWclose(rwops);
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 _loadShader(GPU_ShaderEnum shader_type, std::string source) {
|
||||||
|
Uint32 shader;
|
||||||
|
std::string header = "";
|
||||||
|
GPU_Renderer* renderer = GPU_GetCurrentRenderer();
|
||||||
|
|
||||||
|
// Get size from header
|
||||||
|
if(renderer->shader_language == GPU_LANGUAGE_GLSL)
|
||||||
|
{
|
||||||
|
if(renderer->max_shader_version >= 120)
|
||||||
|
header = "#version 120\n";
|
||||||
|
else
|
||||||
|
header = "#version 110\n"; // Maybe this is good enough?
|
||||||
|
}
|
||||||
|
else if(renderer->shader_language == GPU_LANGUAGE_GLSLES)
|
||||||
|
header = "#version 100\nprecision mediump int;\nprecision mediump float;\n";
|
||||||
|
|
||||||
|
std::string final_source = header + source;
|
||||||
|
|
||||||
|
// Compile the shader
|
||||||
|
shader = GPU_CompileShader(shader_type, final_source.c_str());
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdfml::ShaderProg::loadShader(std::string path, SHADER_TYPE shader_type, GPU_Target* target, GPU_Image* image) {
|
||||||
|
Uint32 s;
|
||||||
|
|
||||||
|
switch (shader_type) {
|
||||||
|
case FRAGMENT:
|
||||||
|
s = loadShaderFromFile(GPU_FRAGMENT_SHADER, path.c_str());
|
||||||
|
frag_int = GPU_LinkShaderProgram(s);
|
||||||
|
|
||||||
|
fragment = GPU_LoadShaderBlock(frag_int, "gpu_Vertex", "gpu_TexCoord", "gpu_Color", "gpu_ModelViewProjectionMatrix");
|
||||||
|
GPU_ActivateShaderProgram(frag_int, &fragment);
|
||||||
|
|
||||||
|
if(image != NULL)
|
||||||
|
{
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(frag_int, "resolution_x"), image->w);
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(frag_int, "resolution_y"), image->h);
|
||||||
|
}
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(frag_int, "screen_w"), target->w);
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(frag_int, "screen_h"), target->h);
|
||||||
|
iTime = GPU_GetUniformLocation(frag_int, "time");
|
||||||
|
break;
|
||||||
|
case VERTEX:
|
||||||
|
s = loadShaderFromFile(GPU_VERTEX_SHADER, path.c_str());
|
||||||
|
vert_int = GPU_LinkShaderProgram(s);
|
||||||
|
|
||||||
|
vertex = GPU_LoadShaderBlock(vert_int, "gpu_Vertex", "gpu_TexCoord", "gpu_Color", "gpu_ModelViewProjectionMatrix");
|
||||||
|
GPU_ActivateShaderProgram(vert_int, &vertex);
|
||||||
|
if(image != NULL)
|
||||||
|
{
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(vert_int, "resolution_x"), image->w);
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(vert_int, "resolution_y"), image->h);
|
||||||
|
}
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(vert_int, "screen_w"), target->w);
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(vert_int, "screen_h"), target->h);
|
||||||
|
iTime = GPU_GetUniformLocation(vert_int, "time");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdfml::ShaderProg::loadShaderFromString(std::string source, SHADER_TYPE shader_type, GPU_Target* target, GPU_Image* image) {
|
||||||
|
Uint32 s;
|
||||||
|
|
||||||
|
switch (shader_type) {
|
||||||
|
case FRAGMENT:
|
||||||
|
s = _loadShader(GPU_FRAGMENT_SHADER, source);
|
||||||
|
frag_int = GPU_LinkShaderProgram(s);
|
||||||
|
|
||||||
|
fragment = GPU_LoadShaderBlock(frag_int, "gpu_Vertex", "gpu_TexCoord", "gpu_Color", "gpu_ModelViewProjectionMatrix");
|
||||||
|
GPU_ActivateShaderProgram(frag_int, &fragment);
|
||||||
|
|
||||||
|
if(image != NULL)
|
||||||
|
{
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(frag_int, "resolution_x"), image->w);
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(frag_int, "resolution_y"), image->h);
|
||||||
|
}
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(frag_int, "screen_w"), target->w);
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(frag_int, "screen_h"), target->h);
|
||||||
|
iTime = GPU_GetUniformLocation(frag_int, "time");
|
||||||
|
break;
|
||||||
|
case VERTEX:
|
||||||
|
s = _loadShader(GPU_VERTEX_SHADER, source);
|
||||||
|
vert_int = GPU_LinkShaderProgram(s);
|
||||||
|
|
||||||
|
vertex = GPU_LoadShaderBlock(vert_int, "gpu_Vertex", "gpu_TexCoord", "gpu_Color", "gpu_ModelViewProjectionMatrix");
|
||||||
|
GPU_ActivateShaderProgram(vert_int, &vertex);
|
||||||
|
if(image != NULL)
|
||||||
|
{
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(vert_int, "resolution_x"), image->w);
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(vert_int, "resolution_y"), image->h);
|
||||||
|
}
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(vert_int, "screen_w"), target->w);
|
||||||
|
GPU_SetUniformf(GPU_GetUniformLocation(vert_int, "screen_h"), target->h);
|
||||||
|
iTime = GPU_GetUniformLocation(vert_int, "time");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdfml::ShaderProg::freeShader() {
|
||||||
|
if (frag_int != NULL)
|
||||||
|
GPU_FreeShaderProgram(frag_int);
|
||||||
|
if (vert_int != NULL)
|
||||||
|
GPU_FreeShaderProgram(vert_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdfml::ShaderProg::updateShader(float elapsed) {
|
||||||
|
if (frag_int != NULL)
|
||||||
|
GPU_ActivateShaderProgram(frag_int, &fragment);
|
||||||
|
if (vert_int != NULL)
|
||||||
|
GPU_ActivateShaderProgram(vert_int, &vertex);
|
||||||
|
if (frag_int != NULL || vert_int != NULL)
|
||||||
|
GPU_SetUniformf(iTime, elapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdfml::ShaderProg::postUpdate() {
|
||||||
|
GPU_ActivateShaderProgram(0, NULL);
|
||||||
|
}
|
31
src/sdfml/shader.hpp
Normal file
31
src/sdfml/shader.hpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef _SHADER_HPP
|
||||||
|
#define _SHADER_HPP
|
||||||
|
#include "../SDL2/SDL.h"
|
||||||
|
#include "../SDL_gpu/SDL_gpu.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
enum SHADER_TYPE {
|
||||||
|
FRAGMENT,
|
||||||
|
VERTEX
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace sdfml {
|
||||||
|
class ShaderProg {
|
||||||
|
public:
|
||||||
|
GPU_ShaderBlock fragment;
|
||||||
|
GPU_ShaderBlock vertex;
|
||||||
|
|
||||||
|
void loadShader(std::string path, SHADER_TYPE shader_type, GPU_Target* target, GPU_Image* image);
|
||||||
|
void loadShaderFromString(std::string source, SHADER_TYPE shader_type, GPU_Target* target, GPU_Image* image);
|
||||||
|
void freeShader();
|
||||||
|
void updateShader(float elapsed);
|
||||||
|
void postUpdate();
|
||||||
|
protected:
|
||||||
|
Uint32 frag_int = NULL;
|
||||||
|
Uint32 vert_int = NULL;
|
||||||
|
|
||||||
|
int iTime = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue