Mentions légales du service

Skip to content
Snippets Groups Projects
Commit 29d6fe3e authored by danh huynh's avatar danh huynh
Browse files

replace all code by version 1.0.2rc

parent 62be9c3c
No related branches found
No related tags found
No related merge requests found
Showing
with 0 additions and 1722 deletions
// GLSL entry point
void main(void) {
fragColor = vec4(0.,0.,0.,1.);
mainImage(fragColor, vtexCoord.xy * iResolution.xy);
}
#version 330
precision highp float;
precision highp int;
precision highp sampler2D;
// Input texture coordinate
in vec2 vtexCoord;
// Output fragment color
out vec4 fragColor;
#include "stdafx.hpp"
#include "shadertoy/BufferConfig.hpp"
using namespace std;
namespace fs = boost::filesystem;
using namespace shadertoy;
bool InputConfig::enabled() const
{
return !id.empty() && !type.empty();
}
InputConfig::InputConfig()
: id(),
type(),
source(),
wrap(GL_REPEAT),
minFilter(GL_LINEAR),
magFilter(GL_LINEAR)
{
}
#include "stdafx.hpp"
#include "shadertoy/BufferConfig.hpp"
#include "shadertoy/ContextConfig.hpp"
using namespace shadertoy;
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/Buffer.hpp"
using namespace shadertoy::OpenGL;
NullBufferError::NullBufferError()
: ShadertoyError("An attempt was made to dereference a null buffer")
{
}
void Buffer::Bind(GLenum target)
{
glCall(glBindBuffer, target, GLuint(*this));
}
void Buffer::Data(GLsizei size, const void *data, GLenum usage)
{
glCall(glNamedBufferData, GLuint(*this), size, data, usage);
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/Caller.hpp"
#if HAS_UNWIND
#include <libunwind.h>
#endif
#define ERROR_PREFIX "OpenGL error: "
using namespace shadertoy::OpenGL;
std::string glErrorToString(GLenum error, const std::string &extraMsg)
{
std::stringstream ss;
ss << ERROR_PREFIX;
switch (error)
{
case GL_NO_ERROR:
ss << "No error.";
break;
case GL_INVALID_ENUM:
ss << "An unacceptable value is specified for an enumerated argument.";
break;
case GL_INVALID_VALUE:
ss << "A numeric argument is out of range.";
break;
case GL_INVALID_OPERATION:
ss << "The specified operation is not allowed in the current state.";
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
ss << "The framebuffer object is not complete.";
break;
case GL_OUT_OF_MEMORY:
ss << "There is not enough memory left to execute the command.";
break;
case GL_STACK_UNDERFLOW:
ss << "An attempt has been made to perform an operation that would cause an internal stack to underflow.";
break;
case GL_STACK_OVERFLOW:
ss << "An attempt has been made to perform an operation that would cause an internal stack to overflow.";
break;
default:
ss << "Unknown error (" << (int)error << ")";
break;
}
if (!extraMsg.empty())
{
ss << std::endl << extraMsg;
}
return ss.str();
}
OpenGLError::OpenGLError(GLenum error, const std::string &extraMsg)
: ShadertoyError(glErrorToString(error, extraMsg))
{
}
namespace shadertoy
{
namespace OpenGL
{
void CheckErrors()
{
GLenum error = glGetError();
if (error != GL_NO_ERROR)
{
#if HAS_UNWIND
std::stringstream ss;
bool first = true;
char buf[256];
unw_cursor_t c;
unw_context_t ctxt;
unw_word_t ip, sp, off;
int ret;
ret = unw_getcontext(&ctxt);
if (ret)
{
// failed to get local context
goto unwind_end;
}
ret = unw_init_local(&c, &ctxt);
if (ret)
{
// failed to get cursor on context
goto unwind_end;
}
while (unw_step(&c) > 0)
{
unw_get_reg(&c, UNW_REG_IP, &ip);
unw_get_reg(&c, UNW_REG_SP, &sp);
ret = unw_get_proc_name(&c, &buf[0], sizeof(buf), &off);
if (first)
{
first = false;
}
else
{
if (ret != 0 && ret != UNW_ENOMEM)
{
ss << "Called from ?:" << std::hex << ip << ":?" << std::endl;
}
else
{
ss << "Called from " << buf << ":" << std::hex << ip << ":" << std::hex << off << std::endl;
}
}
if (strcmp("main", buf) == 0)
break;
}
unwind_end:
throw OpenGLError(error, ss.str());
#else
throw OpenGLError(error, std::string());
#endif
}
}
}
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/Texture.hpp"
#include "shadertoy/OpenGL/Framebuffer.hpp"
using namespace shadertoy::OpenGL;
NullFramebufferError::NullFramebufferError()
: ShadertoyError("An attempt was made to dereference a null framebuffer")
{
}
void Framebuffer::Bind(GLenum target)
{
glCall(glBindFramebuffer, target, GLuint(*this));
}
void Framebuffer::Texture(GLenum attachment, shadertoy::OpenGL::Texture &texture, GLint level)
{
glCall(glNamedFramebufferTexture, GLuint(*this), attachment, GLuint(texture), level);
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/Shader.hpp"
#include "shadertoy/OpenGL/Program.hpp"
using namespace shadertoy::OpenGL;
NullProgramError::NullProgramError()
: ShadertoyError("An attempt was made to dereference a null program")
{
}
UniformLocation::UniformLocation(const Program &program, GLint location)
: _program(GLuint(program)),
_location(location)
{
}
bool UniformLocation::IsActive() const
{
return _location != -1;
}
bool UniformLocation::SetValue(const GLint &v0)
{
if (IsActive())
{
glCall(glProgramUniform1i, _program, _location, v0);
return true;
}
return false;
}
bool UniformLocation::SetValue(const GLfloat &v0)
{
if (IsActive())
{
glCall(glProgramUniform1f, _program, _location, v0);
return true;
}
return false;
}
bool UniformLocation::SetValue(const glm::vec2 &v)
{
if (IsActive())
{
glCall(glProgramUniform2f, _program, _location, v.x, v.y);
return true;
}
return false;
}
bool UniformLocation::SetValue(const glm::vec3 &v)
{
if (IsActive())
{
glCall(glProgramUniform3f, _program, _location, v.x, v.y, v.z);
return true;
}
return false;
}
bool UniformLocation::SetValue(const glm::vec4 &v)
{
if (IsActive())
{
glCall(glProgramUniform4f, _program, _location, v.x, v.y, v.z, v.w);
return true;
}
return false;
}
bool UniformLocation::SetValue(size_t count, const GLint *v0)
{
if (IsActive())
{
glCall(glProgramUniform1iv, _program, _location, count, v0);
return true;
}
return false;
}
bool UniformLocation::SetValue(size_t count, const GLfloat *v0)
{
if (IsActive())
{
glCall(glProgramUniform1fv, _program, _location, count, v0);
return true;
}
return false;
}
bool UniformLocation::SetValue(size_t count, const glm::vec2 *v)
{
if (IsActive())
{
glCall(glProgramUniform2fv, _program, _location, count, reinterpret_cast<const GLfloat*>(v));
return true;
}
return false;
}
bool UniformLocation::SetValue(size_t count, const glm::vec3 *v)
{
if (IsActive())
{
glCall(glProgramUniform3fv, _program, _location, count, reinterpret_cast<const GLfloat*>(v));
return true;
}
return false;
}
bool UniformLocation::SetValue(size_t count, const glm::vec4 *v)
{
if (IsActive())
{
glCall(glProgramUniform4fv, _program, _location, count, reinterpret_cast<const GLfloat*>(v));
return true;
}
return false;
}
ProgramLinkError::ProgramLinkError(GLuint programId, const std::string &log)
: ShadertoyError("OpenGL program linking error"),
_programId(programId),
_log(log)
{
}
ProgramValidateError::ProgramValidateError(GLuint programId, const std::string &log)
: ShadertoyError("OpenGL program validation error"),
_programId(programId),
_log(log)
{
}
void Program::Link()
{
glCall(glLinkProgram, GLuint(*this));
GLint linkStatus;
glCall(glGetProgramiv, GLuint(*this), GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE)
{
throw ProgramLinkError(GLuint(*this), this->Log());
}
}
void Program::Use()
{
glCall(glUseProgram, GLuint(*this));
}
void Program::Validate()
{
glCall(glValidateProgram, GLuint(*this));
GLint validateStatus;
glCall(glGetProgramiv, GLuint(*this), GL_LINK_STATUS, &validateStatus);
if (validateStatus != GL_TRUE)
{
throw ProgramValidateError(GLuint(*this), this->Log());
}
}
UniformLocation Program::GetUniformLocation(const GLchar *name)
{
GLint location = glCall(glGetUniformLocation, GLuint(*this), name);
return UniformLocation(*this, location);
}
void Program::AttachShader(const Shader &shader)
{
glCall(glAttachShader, GLuint(*this), GLuint(shader));
}
std::string Program::Log()
{
// Get log length
GLint infoLogLength = 0;
glCall(glGetProgramiv, GLuint(*this), GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength == 0)
return std::string();
// Get log
std::vector<GLchar> logStr(infoLogLength);
glCall(glGetProgramInfoLog, GLuint(*this), infoLogLength, nullptr, logStr.data());
// exclude the null character from the range passed to string constructor
return std::string(logStr.begin(), logStr.end() - 1);
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/Query.hpp"
using namespace shadertoy::OpenGL;
NullQueryError::NullQueryError()
: ShadertoyError("An attempt was made to dereference a null query")
{
}
GLuint QueryAllocator::Create(GLenum target)
{
GLuint id;
glCall(glCreateQueries, target, 1, &id);
return id;
}
void QueryAllocator::Delete(GLuint resource)
{
glCall(glDeleteQueries, 1, &resource);
}
Query::Query(GLenum target)
: Resource(Allocator().Create(target))
{
}
void Query::Begin(GLenum target)
{
glCall(glBeginQuery, target, GLuint(*this));
}
void Query::End(GLenum target)
{
glCall(glEndQuery, target);
}
void Query::GetObjectiv(GLenum pname, GLint *params)
{
glCall(glGetQueryObjectiv, GLuint(*this), pname, params);
}
void Query::GetObjectui64v(GLenum pname, GLuint64 *params)
{
glCall(glGetQueryObjectui64v, GLuint(*this), pname, params);
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/Renderbuffer.hpp"
using namespace shadertoy::OpenGL;
NullRenderbufferError::NullRenderbufferError()
: ShadertoyError("An attempt was made to dereference a null renderbuffer")
{
}
void Renderbuffer::Bind(GLenum target)
{
glCall(glBindRenderbuffer, target, GLuint(*this));
}
void Renderbuffer::Storage(GLenum internalFormat, GLsizei width, GLsizei height)
{
glCall(glNamedRenderbufferStorage, GLuint(*this), internalFormat, width, height);
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/Caller.hpp"
#include "shadertoy/OpenGL/Shader.hpp"
using namespace shadertoy::OpenGL;
NullShaderError::NullShaderError()
: ShadertoyError("An attempt was made to dereference a null shader")
{
}
ShaderCompilationError::ShaderCompilationError(GLuint shaderId, const std::string &log)
: ShadertoyError("OpenGL shader compilation error"),
_shaderId(shaderId),
_log(log)
{
}
GLuint ShaderAllocator::Create(GLenum shaderType)
{
return glCall(glCreateShader, shaderType);
}
void ShaderAllocator::Delete(GLuint resource)
{
glCall(glDeleteShader, resource);
}
Shader::Shader(GLenum shaderType)
: Resource(Allocator().Create(shaderType))
{
}
void Shader::Source(const std::string &string)
{
const GLchar *cstr = string.c_str();
glCall(glShaderSource, GLuint(*this), 1, &cstr, nullptr);
}
void Shader::Source(const std::vector<std::string> &string)
{
std::vector<const char *> cstr(string.size());
std::transform(string.begin(), string.end(), cstr.begin(),
[] (const std::string &src) {
return src.c_str();
});
glCall(glShaderSource, GLuint(*this), string.size(), cstr.data(), nullptr);
}
void Shader::Compile()
{
// Try to compile shader
glCall(glCompileShader, GLuint(*this));
// Get status
GLint compileStatus;
glCall(glGetShaderiv, GLuint(*this), GL_COMPILE_STATUS, &compileStatus);
// Throw error if shader could not be compiled
if (compileStatus != GL_TRUE)
{
throw ShaderCompilationError(GLuint(*this), this->Log());
}
}
std::string Shader::Log()
{
// Get log length
GLint infoLogLength = 0;
glCall(glGetShaderiv, GLuint(*this), GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength == 0)
return std::string();
// Get log
std::vector<GLchar> logStr(infoLogLength);
glCall(glGetShaderInfoLog, GLuint(*this), infoLogLength, nullptr, logStr.data());
// exclude the null character from the range passed to string constructor
return std::string(logStr.begin(), logStr.end() - 1);
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/Texture.hpp"
using namespace shadertoy::OpenGL;
NullTextureError::NullTextureError()
: ShadertoyError("An attempt was made to dereference a null texture")
{
}
GLuint TextureAllocator::Create(GLenum target)
{
GLuint res;
glCall(glCreateTextures, target, 1, &res);
return res;
}
void TextureAllocator::Delete(GLuint resource)
{
glCall(glDeleteTextures, 1, &resource);
}
Texture::Texture(GLenum target)
: Resource(Allocator().Create(target))
{
}
void Texture::Bind(GLenum target)
{
glCall(glBindTexture, target, GLuint(*this));
}
void Texture::Parameter(GLenum pname, GLint param)
{
glCall(glTextureParameteri, GLuint(*this), pname, param);
}
void Texture::Parameter(GLenum pname, GLfloat param)
{
glCall(glTextureParameterf, GLuint(*this), pname, param);
}
void Texture::Image2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data)
{
glCall(glTextureImage2DEXT, GLuint(*this), target, level, internalFormat, width, height, border, format, type, data);
}
void Texture::GenerateMipmap()
{
glCall(glGenerateTextureMipmap, GLuint(*this));
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/OpenGL.hpp"
#include "Resources.h"
#include "shadertoy/ContextConfig.hpp"
#include "shadertoy/UniformState.hpp"
#include "shadertoy/BufferConfig.hpp"
#include "shadertoy/ToyBuffer.hpp"
#include "shadertoy/TextureEngine.hpp"
#include "shadertoy/ShaderCompiler.hpp"
#include "shadertoy/RenderContext.hpp"
namespace fs = boost::filesystem;
using namespace std;
using namespace shadertoy;
using shadertoy::OpenGL::glCall;
shared_ptr<TextureEngine> RenderContext::BuildTextureEngine()
{
auto engine = make_shared<TextureEngine>(config);
engine->RegisterHandler("buffer", InputHandler([this]
(const InputConfig &inputConfig,
bool &skipTextureOptions,
bool &skipCache,
bool &framebufferSized)
{
skipTextureOptions = true;
skipCache = true;
// No need to reallocate buffer textures, this is handled by the buffer
// itself
framebufferSized = false;
auto &bufferConfigs = config.bufferConfigs;
auto bufferIt = bufferConfigs.find(inputConfig.source);
if (bufferIt == bufferConfigs.end())
{
BOOST_LOG_TRIVIAL(warning) << "buffer '" << inputConfig.source
<< "' not found for input " << inputConfig.id;
return shared_ptr<OpenGL::Texture>();
}
else
{
if (frameCount == 0)
{
BOOST_LOG_TRIVIAL(info) << "binding '" << inputConfig.source
<< "' to input " << inputConfig.id;
}
auto texture = buffers[inputConfig.source]->GetSourceTexture();
int minFilter = max((int)inputConfig.minFilter, GL_LINEAR),
magFilter = (int)inputConfig.magFilter;
texture->Parameter(GL_TEXTURE_MAG_FILTER, magFilter);
texture->Parameter(GL_TEXTURE_MIN_FILTER, minFilter);
texture->Parameter(GL_TEXTURE_WRAP_S, inputConfig.wrap);
texture->Parameter(GL_TEXTURE_WRAP_T, inputConfig.wrap);
return texture;
}
}));
return engine;
}
void RenderContext::PreInitializeBuffers()
{
}
void RenderContext::PostInitializeBuffers()
{
}
void RenderContext::LoadBufferSources(vector<pair<string, string>> &sources)
{
}
void RenderContext::PostBufferRender(const string &name,
shared_ptr<ToyBuffer> &buffer)
{
}
void RenderContext::BindInputs(vector<shared_ptr<BoundInputsBase>> &inputs,
OpenGL::Program &program)
{
}
RenderContext::RenderContext(ContextConfig &config)
: config(config),
screenVs(GL_VERTEX_SHADER),
screenFs(GL_FRAGMENT_SHADER),
frameCount(0)
{
textureEngine = BuildTextureEngine();
}
void RenderContext::Initialize()
{
// Initialize constant uniforms
state.V<iResolution>() = glm::vec3(config.width, config.height, 1.0f);
// Note that this will be overriden once query measurements are available
state.V<iTimeDelta>() = 1.0f / (float) config.targetFramerate;
state.V<iFrameRate>() = (float) config.targetFramerate;
state.V<iChannel0>() = 1;
state.V<iChannel1>() = 2;
state.V<iChannel2>() = 3;
state.V<iChannel3>() = 4;
state.V<iChannelTime>() = { 0.f, 0.f, 0.f, 0.f };
state.V<iSampleRate>() = 48000.f;
// Compile screen quad vertex shader
screenVs.Source(string(screenQuad_vsh, screenQuad_vsh + screenQuad_vsh_size));
screenVs.Compile();
// Compile screen quad fragment shader
screenFs.Source(string(screenQuad_fsh, screenQuad_fsh + screenQuad_fsh_size));
screenFs.Compile();
// Prepare screen quad program
screenProg.AttachShader(screenVs);
screenProg.AttachShader(screenFs);
// Compile screen program
screenProg.Link();
// Setup screen textures
screenProg.Use();
screenProg.GetUniformLocation("screenTexture").SetValue(0);
// Initialize the texture engine
textureEngine->Initialize();
// Prepare screen quad geometry
GLfloat coords[] = {
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f
};
GLuint indices[] = {
0, 1, 2,
0, 2, 3
};
// Setup coords
screenQuadCorners.Data(sizeof(coords),
static_cast<const GLvoid*>(&coords[0]), GL_STATIC_DRAW);
// Setup indices
screenQuadIndices.Data(sizeof(indices),
static_cast<const GLvoid*>(&indices[0]), GL_STATIC_DRAW);
// Initialize buffers
InitializeBuffers();
}
void RenderContext::InitializeBuffers()
{
// Invoke callback
PreInitializeBuffers();
// Prepare the define wrapper
ostringstream oss;
for (auto define : config.preprocessorDefines)
{
oss << "#define " << define.first;
if (!define.second.empty()) {
oss << " " << define.second;
}
oss << endl;
}
defineWrapper = oss.str();
// Initialize program buffer
auto bufferConfigs = config.bufferConfigs;
for (auto it = bufferConfigs.begin(); it != bufferConfigs.end(); ++it)
{
auto buf = make_shared<ToyBuffer>(*this, it->first);
buf->Initialize(config.width, config.height);
buffers.insert(make_pair(it->first, buf));
}
// Setup position and texCoord attributes for shaders
screenQuadCorners.Bind(GL_ARRAY_BUFFER);
screenQuadIndices.Bind(GL_ELEMENT_ARRAY_BUFFER);
vector<OpenGL::Program *> programs{&screenProg};
GLint location;
for (auto it = programs.begin(); it != programs.end(); ++it)
{
// Bind input "position" to vertex locations (3 floats)
location = glCall(glGetAttribLocation, GLuint(**it), "position");
glCall(glVertexAttribPointer, location, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);
glCall(glEnableVertexAttribArray, location);
// Bind input "texCoord" to vertex texture coordinates (2 floats)
location = glCall(glGetAttribLocation, GLuint(**it), "texCoord");
glCall(glVertexAttribPointer, location, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
glCall(glEnableVertexAttribArray, location);
}
lastTexture = weak_ptr<OpenGL::Texture>();
// Invoke callback
PostInitializeBuffers();
}
void RenderContext::AllocateTextures()
{
// Drop the reference to screenQuadTexture, it will be recreated if needed
screenQuadTexture = shared_ptr<OpenGL::Texture>();
// Reallocate buffer textures
for (auto &pair : buffers)
pair.second->AllocateTextures(config.width, config.height);
// Reallocate inputs
textureEngine->ClearState(true);
// Update the iResolution uniform, as this method can be called after a
// framebuffer size change
state.V<iResolution>() = glm::vec3(config.width, config.height, 1.0f);
}
void RenderContext::ClearState()
{
// Clear previous input textures
textureEngine->ClearState();
// Clear previous buffers
buffers.clear();
// Clear the source cache
sourceCache.clear();
}
void RenderContext::Render()
{
for (auto pair : buffers)
{
pair.second->Render();
lastTexture = pair.second->GetSourceTexture();
PostBufferRender(pair.first, pair.second);
}
frameCount++;
}
void RenderContext::DoReadWriteCurrentFrame(GLuint &texIn, GLuint &texOut)
{
if (auto currentTex = lastTexture.lock())
{
// Allocate the target screen quad texture as it is requested
if (!screenQuadTexture)
{
// Create texture object
screenQuadTexture = make_shared<OpenGL::Texture>(GL_TEXTURE_2D);
// Setup screenQuadTexture
screenQuadTexture->Parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
screenQuadTexture->Parameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
screenQuadTexture->Parameter(GL_TEXTURE_WRAP_S, GL_REPEAT);
screenQuadTexture->Parameter(GL_TEXTURE_WRAP_T, GL_REPEAT);
screenQuadTexture->Image2D(GL_TEXTURE_2D, 0, GL_RGBA32F,
config.width, config.height, 0, GL_BGRA, GL_FLOAT, nullptr);
}
texIn = *currentTex;
texOut = *screenQuadTexture;
lastTexture = screenQuadTexture;
}
else
{
throw runtime_error("DoReadWriteCurrentFrame: lastTexture pointer has expired!");
}
}
void RenderContext::DoReadCurrentFrame(GLuint &texIn)
{
if (auto currentTex = lastTexture.lock())
{
texIn = *currentTex;
}
else
{
throw runtime_error("DoReadCurrentFrame: lastTexture pointer has expired!");
}
}
void RenderContext::BuildBufferShader(const string &id,
OpenGL::Shader &fs)
{
auto &bufferConfig(config.bufferConfigs[id]);
// Load all source parts
ShaderCompiler compiler;
auto &sources(compiler.Sources());
// Load callback sources
LoadBufferSources(sources);
// Add define wrapper
sources.insert(sources.begin(),
make_pair(string("generated:define-wrapper"), defineWrapper));
// Add sources
for (auto &shaderFile : bufferConfig.shaderFiles)
{
sources.push_back(make_pair(shaderFile.string(), LoadShaderSource(shaderFile)));
}
// Add default wrapper around code
sources.insert(sources.begin(), make_pair(
string("internal:wrapper-header"),
string(wrapper_header_fsh, wrapper_header_fsh + wrapper_header_fsh_size)));
// Add source from uniform declarations
sources.insert(sources.begin() + 1, make_pair(
string("generated:shader-inputs"),
state.GetDefinitions()));
// Add footer
sources.push_back(make_pair(
string("internal:wrapper-footer"),
string(wrapper_footer_fsh, wrapper_footer_fsh + wrapper_footer_fsh_size)));
// Load sources into fragment shader and compile
compiler.Compile(fs);
}
const GLchar *RenderContext::LoadShaderSource(const fs::path &path) throw(runtime_error)
{
fs::path shaderPath(fs::canonical(path));
ifstream src(shaderPath.string().c_str());
string loadedSource;
loadedSource.assign(istreambuf_iterator<char>(src), istreambuf_iterator<char>());
if (loadedSource.back() != '\n') {
loadedSource += "\n";
}
sourceCache.insert(make_pair(shaderPath.string(), loadedSource));
BOOST_LOG_TRIVIAL(info) << "loaded " << shaderPath;
return sourceCache.find(shaderPath.string())->second.c_str();
}
const GLchar *RenderContext::GetDefineWrapper() const
{
return defineWrapper.c_str();
}
vector<shared_ptr<BoundInputsBase>> RenderContext::GetBoundInputs(OpenGL::Program &program)
{
vector<shared_ptr<BoundInputsBase>> result;
// External inputs
BindInputs(result, program);
// Default inputs
result.insert(result.begin(), state.GetBoundInputs(program));
return result;
}
void RenderContext::Clear(float level)
{
glCall(glViewport, 0, 0, config.width, config.height);
glCall(glClearColor, level, level, level, level);
glCall(glClear, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void RenderContext::RenderScreenQuad()
{
screenQuadCorners.Bind(GL_ARRAY_BUFFER);
glCall(glDrawElements, GL_TRIANGLES, 3 * 2, GL_UNSIGNED_INT, nullptr);
}
void RenderContext::RenderScreenQuad(OpenGL::Query &timerQuery)
{
screenQuadCorners.Bind(GL_ARRAY_BUFFER);
timerQuery.Begin(GL_TIME_ELAPSED);
glCall(glDrawElements, GL_TRIANGLES, 3 * 2, GL_UNSIGNED_INT, nullptr);
timerQuery.End(GL_TIME_ELAPSED);
}
void RenderContext::BindResult()
{
// Prepare prog and texture
screenProg.Use();
glCall(glActiveTexture, GL_TEXTURE0);
lastTexture.lock()->Bind(GL_TEXTURE_2D);
}
OpenGL::Shader &RenderContext::GetScreenQuadVertexShader()
{
return screenVs;
}
shared_ptr<ToyBuffer> RenderContext::GetBufferByName(const string &name)
{
if (name.empty())
{
if (buffers.empty())
{
return shared_ptr<ToyBuffer>();
}
return buffers.rbegin()->second;
}
else
{
auto it = buffers.find(name);
if (it == buffers.end())
{
return shared_ptr<ToyBuffer>();
}
return it->second;
}
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/OpenGL.hpp"
#include "shadertoy/ShaderCompiler.hpp"
using namespace std;
using namespace shadertoy;
ShaderCompiler::ShaderCompiler()
: namedSources()
{
}
void ShaderCompiler::Compile(OpenGL::Shader &shader)
{
// Transform pairs into list of C strings
vector<std::string> sources(namedSources.size());
transform(namedSources.begin(), namedSources.end(), sources.begin(),
[] (const pair<string, string> &namedSource) {
return namedSource.second;
});
// Also, build a line count
vector<int> lineCounts(namedSources.size());
transform(namedSources.begin(), namedSources.end(), lineCounts.begin(),
[] (const pair<string, string> &namedSource) {
return count(namedSource.second.begin(),
namedSource.second.end(),
'\n');
});
// Load sources in fragment shader and compile
try
{
shader.Source(sources);
shader.Compile();
}
catch (OpenGL::ShaderCompilationError &ex)
{
// Reparse log and replace sources with their actual names
std::stringstream is(ex.log()), os;
std::string msg;
while (!is.eof())
{
char c, d;
size_t pid, pline;
// Read one message
getline(is, msg);
// Try parsing message
std::stringstream msgis(msg);
// Matches ID(LINE.
// ID:LINE.
msgis >> pid >> c >> pline >> d;
if (msgis.fail())
{
// Parsing failed
os << msg << endl;
}
else
{
// Parsing succeeded, find the source part which contains the
// actual error
size_t lc, lcn, li = 0;
for (lc = 0, lcn = 0;
li < lineCounts.size();
li++)
{
lc = lcn;
lcn += lineCounts.at(li);
if (lcn > pline) break;
}
// If li exceeds known programs, an error occurred, pass the
// message verbatim
if (li >= lineCounts.size())
{
os << msg << endl;
continue;
}
// Output a formatted message with the error
os << namedSources.at(li).first
<< c
<< (pline - lc)
<< d
<< msgis.rdbuf()
<< endl;
}
}
// Update exception and rethrow
throw OpenGL::ShaderCompilationError(GLuint(shader), os.str());
}
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
using namespace shadertoy;
ShadertoyError::ShadertoyError(const std::string &what_arg)
: std::runtime_error(what_arg)
{
}
ShadertoyError::ShadertoyError(const char *what_arg)
: std::runtime_error(what_arg)
{
}
This diff is collapsed.
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/OpenGL.hpp"
#include "shadertoy/BufferConfig.hpp"
#include "shadertoy/ContextConfig.hpp"
#include "shadertoy/UniformState.hpp"
#include "shadertoy/ToyBuffer.hpp"
#include "shadertoy/TextureEngine.hpp"
#include "shadertoy/RenderContext.hpp"
#include "Resources.h"
using namespace std;
namespace fs = boost::filesystem;
using namespace shadertoy;
using shadertoy::OpenGL::glCall;
ToyBuffer::ToyBuffer(RenderContext &context,
const std::string &id)
: context(context),
id(id),
fs(GL_FRAGMENT_SHADER),
boundInputs(),
timeDeltaQuery(GL_TIME_ELAPSED)
{
}
void ToyBuffer::Initialize(int width, int height)
{
auto &config(context.GetConfig().bufferConfigs[id]);
// Attach the vertex shader for the screen quad
program.AttachShader(context.GetScreenQuadVertexShader());
// Load the fragment shader for this buffer
context.BuildBufferShader(id, fs);
// Attach shader
program.AttachShader(fs);
// Link the program
program.Link();
// Use the program
program.Use();
// Dump the program if requested
if (context.GetConfig().dumpShaders)
{
GLenum err;
// Get GL program id
GLuint progId = GLuint(program);
// Allocate buffer
GLint len, actLen;
glCall(glGetProgramiv, progId, GL_PROGRAM_BINARY_LENGTH, &len);
char *progBinary = new char[len];
// Get binary
GLenum format;
glGetProgramBinary(progId, len, &actLen, &format, progBinary);
if ((err = glGetError()) != GL_NO_ERROR)
{
delete[] progBinary;
std::stringstream ss;
ss << "could not get program binary: " << err;
throw std::runtime_error(ss.str());
}
// Store in file
fs::path name(config.shaderFiles.front());
name.replace_extension(".dump");
BOOST_LOG_TRIVIAL(info) << "dumping program binary to " << name;
ofstream ofs(name.string().c_str(), std::ofstream::binary);
if (!ofs.is_open())
{
delete[] progBinary;
std::stringstream ss;
ss << "could not open output file " << name.string();
throw std::runtime_error(ss.str());
}
ofs.write(progBinary, actLen);
ofs.close();
delete[] progBinary;
}
// Bind uniform inputs
boundInputs = context.GetBoundInputs(program);
// Allocate render textures
AllocateTextures(width, height);
}
void ToyBuffer::AllocateTextures(int width, int height)
{
// Initialize buffer textures
InitializeRenderTexture(sourceTex, width, height);
InitializeRenderTexture(targetTex, width, height);
// Setup render buffers
targetTex->Bind(GL_TEXTURE_2D);
targetRbo.Bind(GL_RENDERBUFFER);
targetRbo.Storage(GL_DEPTH_COMPONENT, width, height);
}
void ToyBuffer::Render()
{
auto &config(context.GetConfig().bufferConfigs[id]);
// Update renderbuffer to use the correct target texture
targetTex->Bind(GL_TEXTURE_2D);
targetRbo.Bind(GL_RENDERBUFFER);
targetFbo.Bind(GL_DRAW_FRAMEBUFFER);
targetFbo.Texture(GL_COLOR_ATTACHMENT0, *targetTex, 0);
// Prepare the render target
context.Clear(0.f);
// Setup program and its uniforms
program.Use();
// Override values in bound inputs 0 (ShaderToy inputs)
auto &resolutions(static_pointer_cast<ShaderInputsType::BoundInputs>(boundInputs[0])
->State.V<iChannelResolution>());
// Setup the texture targets
for (int i = 0; i < 4; ++i)
{
glCall(glActiveTexture, GL_TEXTURE0 + i + 1);
// Following have side effects, ensure it runs after we selected the new
// texture unit
auto &texture = context.GetTextureEngine()
.GetInputTexture(config.inputConfig[i]);
texture.Bind(GL_TEXTURE_2D);
glCall(glGetTexLevelParameterfv, GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &resolutions[i][0]);
glCall(glGetTexLevelParameterfv, GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &resolutions[i][1]);
resolutions[i][2] = 1.0f;
}
// Try to set iTimeDelta
GLint available = 0;
timeDeltaQuery.GetObjectiv(GL_QUERY_RESULT_AVAILABLE, &available);
if (available)
{
// Result available, set uniform value
GLuint64 timeDelta;
timeDeltaQuery.GetObjectui64v(GL_QUERY_RESULT, &timeDelta);
static_pointer_cast<ShaderInputsType::BoundInputs>(boundInputs[0])
->State.V<iTimeDelta>() = timeDelta / 1e9;
}
// Set all uniforms
for (auto &inputs : boundInputs)
inputs->Apply();
// Render the program
context.RenderScreenQuad(timeDeltaQuery);
// Swap texture object pointers
swap(sourceTex, targetTex);
}
unsigned long long ToyBuffer::GetElapsedTime()
{
GLint available = 0;
// Wait for result to be available
while (!available)
{
timeDeltaQuery.GetObjectiv(GL_QUERY_RESULT_AVAILABLE, &available);
}
// Fetch result
GLuint64 result;
timeDeltaQuery.GetObjectui64v(GL_QUERY_RESULT, &result);
return result;
}
void ToyBuffer::InitializeRenderTexture(shared_ptr<OpenGL::Texture> &texptr, int width, int height)
{
// Only create a texture object if it is necessary
if (!texptr)
texptr = make_shared<OpenGL::Texture>(GL_TEXTURE_2D);
// Allocate texture storage according to width/height
texptr->Parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
texptr->Parameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
texptr->Parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texptr->Parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texptr->Image2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_BGRA,
GL_UNSIGNED_BYTE, nullptr);
// Clear the frame accumulator so it doesn't contain garbage
float black[4] = {0.f};
glCall(glClearTexImage, GLuint(*texptr),
0,
GL_BGRA,
GL_FLOAT,
black);
}
#include "stdafx.hpp"
#include "shadertoy/ShadertoyError.hpp"
#include "shadertoy/OpenGL/OpenGL.hpp"
#include "shadertoy/UniformState.hpp"
#define IMPLEMENT_UNIFORM_STATE
#include "shadertoy/UniformState_impl.hpp"
#include "stdafx.hpp"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment