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 "sdfml/music.hpp"
|
||||
#include "sdfml/shader.hpp"
|
||||
|
||||
#include "SDL_gpu/SDL_gpu.h"
|
||||
|
||||
|
@ -100,6 +101,8 @@ inline std::string _GetCurrentDirectory()
|
|||
|
||||
namespace sdfml {
|
||||
|
||||
static double elapsed;
|
||||
|
||||
inline int llog(string prefix, string msg, lLOG_TYPE type = NORMAL, string file = "???.cpp", int line = 0) {
|
||||
clock_t now = std::clock();
|
||||
|
||||
|
@ -187,6 +190,8 @@ namespace sdfml {
|
|||
|
||||
Vector3<Uint8> color;
|
||||
|
||||
ShaderProg shader;
|
||||
|
||||
virtual void create(int x, int y, string path) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
|
@ -198,6 +203,9 @@ namespace sdfml {
|
|||
color.g = 255;
|
||||
color.b = 255;
|
||||
}
|
||||
virtual void addShader(std::string path) {
|
||||
shader.loadShader(path, FRAGMENT, mContext.gpu_render, _tex_gpu);
|
||||
}
|
||||
GPU_Rect *r;
|
||||
virtual void update(float elapsed) {
|
||||
_x = x+offset.x;
|
||||
|
@ -206,14 +214,17 @@ namespace sdfml {
|
|||
r = &_src_rect;
|
||||
if (r->w == 0)
|
||||
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_BlitRectX(_tex_gpu, r, mContext.gpu_render, &dst, angle, NULL, NULL, GPU_FLIP_NONE);
|
||||
shader.postUpdate();
|
||||
}
|
||||
virtual void destroy() {
|
||||
_x = 0;
|
||||
_y = 0;
|
||||
_w = 0;
|
||||
_h = 0;
|
||||
shader.freeShader();
|
||||
GPU_FreeImage(_tex_gpu);
|
||||
}
|
||||
virtual void updateCamera(SDL_Rect* camera) {
|
||||
|
@ -466,8 +477,6 @@ namespace sdfml {
|
|||
return FRAMERATE*time;
|
||||
}
|
||||
|
||||
static double elapsed;
|
||||
|
||||
inline int update() {
|
||||
int lastUpdate = SDL_GetTicks();
|
||||
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