You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
5.2 KiB
158 lines
5.2 KiB
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "shadertoy_shader.h"
|
|
#include "utils.h"
|
|
|
|
#define _USE_MATH_DEFINES
|
|
#include <math.h>
|
|
|
|
namespace {
|
|
bool CompileShader10(GLuint shader, const std::string& shader_string) {
|
|
std::string prefix = "#version 100\n";
|
|
std::string string_with_prefix = prefix + shader_string;
|
|
const char* shader_str[] = { string_with_prefix.data() };
|
|
glShaderSource(shader, 1, shader_str, NULL);
|
|
glCompileShader(shader);
|
|
|
|
GLint success;
|
|
GLchar infoLog[512];
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
|
if (!success)
|
|
{
|
|
glGetShaderInfoLog(shader, 512, NULL, infoLog);
|
|
LOGI("Shader Failed to compile: %s -- %s\n", *shader_str, infoLog);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}; // namespace
|
|
|
|
|
|
ShadertoyShader::ShadertoyShader() :
|
|
uiResolution_(-1), uiGlobalTime_(-1), uiFrame_(-1), uiTimeDelta_(-1),
|
|
uiChannel0_(-1), unViewport_(-1), unCorners_(-1), shader_program_(0) {
|
|
|
|
GLuint tex_ids[4];
|
|
glGenTextures(4, &tex_ids[0]);
|
|
for (int ii = 0; ii < 4; ii++) {
|
|
input_textures_[ii].width = 0;
|
|
input_textures_[ii].height = 0;
|
|
input_textures_[ii].id = tex_ids[ii];
|
|
}
|
|
}
|
|
|
|
ShadertoyShader::~ShadertoyShader() {
|
|
GLuint ids[] = { input_textures_[0].id, input_textures_[1].id, input_textures_[2].id, input_textures_[3].id, };
|
|
glDeleteTextures(4, ids);
|
|
}
|
|
|
|
void ShadertoyShader::CreateShaderFromString(const std::string& shader_string) {
|
|
CreateShader(shader_string);
|
|
}
|
|
|
|
void ShadertoyShader::GetUniformLocations() {
|
|
glUseProgram(shader_program_);
|
|
uiResolution_ = glGetUniformLocation(shader_program_, "iResolution");
|
|
uiGlobalTime_ = glGetUniformLocation(shader_program_, "iGlobalTime");
|
|
uiFrame_ = glGetUniformLocation(shader_program_, "iFrame");
|
|
uiTimeDelta_ = glGetUniformLocation(shader_program_, "iTimeDelta");
|
|
uiChannel0_ = glGetUniformLocation(shader_program_, "iChannel0");
|
|
|
|
if (uiChannel0_ != -1)
|
|
glUniform1i(uiChannel0_, 0);
|
|
|
|
unViewport_ = glGetUniformLocation(shader_program_, "unViewport");
|
|
unCorners_ = glGetUniformLocation(shader_program_, "unCorners");
|
|
|
|
glUseProgram(0);
|
|
}
|
|
|
|
void ShadertoyShader::CreateShader(const std::string fragment_string) {
|
|
std::string vertex_string = SHADER0([]() {
|
|
attribute vec2 pos;
|
|
void main() {
|
|
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
|
}
|
|
});
|
|
|
|
std::string shader_toy_fragment_header = SHADER0([]() {
|
|
precision highp float;
|
|
uniform vec3 iResolution;
|
|
uniform float iGlobalTime;
|
|
uniform vec4 iMouse;
|
|
uniform int iFrame;
|
|
uniform float iTimeDelta;
|
|
uniform vec3 iChannelResolution[4];
|
|
uniform sampler2D iChannel0;
|
|
vec4 texture2DGrad(sampler2D s, in vec2 uv, vec2 gx, vec2 gy) { return texture2D(s, uv); }
|
|
vec4 texture2DLod(sampler2D s, in vec2 uv, in float lod) { return texture2D(s, uv); }
|
|
void mainImage(out vec4 c, in vec2 f);
|
|
});
|
|
|
|
std::string shader_toy_fragment_footer = SHADER0([]() {
|
|
void main(void) {
|
|
vec4 shader_color = vec4(0, 0, 0, 1);
|
|
mainImage(shader_color, gl_FragCoord.xy);
|
|
shader_color.w = 1.0;
|
|
gl_FragColor = shader_color;
|
|
}
|
|
});
|
|
|
|
std::string complete_fragment_string = shader_toy_fragment_header + fragment_string + shader_toy_fragment_footer;
|
|
|
|
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
|
CompileShader10(vertex_shader, vertex_string);
|
|
|
|
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
CompileShader10(fragment_shader, complete_fragment_string);
|
|
|
|
// Link shaders
|
|
shader_program_ = glCreateProgram();
|
|
LinkProgram(shader_program_, vertex_shader, fragment_shader);
|
|
|
|
GetUniformLocations();
|
|
|
|
glDeleteShader(vertex_shader);
|
|
glDeleteShader(fragment_shader);
|
|
}
|
|
|
|
void ShadertoyShader::PrepareForDraw(int width, int height, float global_time, int frame, float time_delta) {
|
|
glUseProgram(shader_program_);
|
|
|
|
// Set the uniforms
|
|
if (uiResolution_ != -1)
|
|
glUniform3f(uiResolution_, (float)width, (float)height, 1);
|
|
if (uiGlobalTime_ != -1)
|
|
glUniform1f(uiGlobalTime_, global_time);
|
|
if (uiFrame_ != -1)
|
|
glUniform1f(uiFrame_, (float)frame);
|
|
if (uiTimeDelta_ != -1)
|
|
glUniform1f(uiTimeDelta_, time_delta);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, input_textures_[0].id);
|
|
glActiveTexture(GL_TEXTURE1);
|
|
glBindTexture(GL_TEXTURE_2D, input_textures_[1].id);
|
|
glActiveTexture(GL_TEXTURE2);
|
|
glBindTexture(GL_TEXTURE_2D, input_textures_[2].id);
|
|
glActiveTexture(GL_TEXTURE3);
|
|
glBindTexture(GL_TEXTURE_2D, input_textures_[3].id);
|
|
|
|
if (unViewport_ != -1)
|
|
glUniform4f(unViewport_, 0, 0, (float)width, (float)height);
|
|
}
|