void ShaderProgram::CreateAndLinkProgram(std::string vertFilename, std::string fragFilename) { _handler = _graphics.CreateProgram(); AttachShader(vertFilename); AttachShader(fragFilename); Link(); }
ShaderProgram::ShaderProgram(std::string vertex_shader_filename, std::string tessellation_control_shader_filename, std::string tessellation_eval_shader_filename, std::string geometry_shader_filename, std::string fragment_shader_filename) { if (vertex_shader_filename != "") { auto v_source = FileReader::ReadFromFile(vertex_shader_filename); AttachShader(GL_VERTEX_SHADER, v_source); } if (tessellation_control_shader_filename != "") { auto t_c_source = FileReader::ReadFromFile(tessellation_control_shader_filename); AttachShader(GL_TESS_CONTROL_SHADER, t_c_source); } if (tessellation_eval_shader_filename != "") { auto t_e_source = FileReader::ReadFromFile(tessellation_eval_shader_filename); AttachShader(GL_TESS_EVALUATION_SHADER, t_e_source); } if (geometry_shader_filename != "") { auto g_source = FileReader::ReadFromFile(geometry_shader_filename); AttachShader(GL_GEOMETRY_SHADER, g_source); } if (fragment_shader_filename != "") { auto f_source = FileReader::ReadFromFile(fragment_shader_filename); AttachShader(GL_FRAGMENT_SHADER, f_source); } //Link shaders ConfigureShaderProgram(); //Detach shaders after successful linking for (GLuint shader_program : shader_programs_) { glDetachShader(prog, shader_program); } }
GLuint LinkShaders3(GLuint vertShader, GLuint geomShader, GLuint fragShader) { GLuint program = CreateProgram(); assert(vertShader || fragShader); if (vertShader) AttachShader(program, vertShader); if (geomShader) AttachShader(program, geomShader); if (fragShader) AttachShader(program, fragShader); LinkProgram(program); /* check link */ { GLint stat; GetProgramiv(program, GL_LINK_STATUS, &stat); if (!stat) { GLchar log[1000]; GLsizei len; GetProgramInfoLog(program, 1000, &len, log); wxLogError(wxT("BR24radar_pi: problem linking program: %s"), log); return 0; } } return program; }
GLuint LoadShader() { GLuint program = glCreateProgram(); AttachShader(program, GL_VERTEX_SHADER, ID_VERTEX_SHADER); AttachShader(program, GL_FRAGMENT_SHADER, ID_FRAGMENT_SHADER); glLinkProgram(program); glUseProgram(program); return program; }
static GLuint Load( const char * vert, const char * geom, const char * frag ) { GLuint prog = glCreateProgram(); if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert ); if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom ); if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag ); glLinkProgram( prog ); CheckStatus( prog ); return prog; }
void CGizmoTransformRender::Initialize() { if (!m_Program) { //gizmo_ogl_LoadFunctions(); m_Program = glCreateProgram(); static const char vertexShader[] = "" "#if __VERSION__ < 130\n" "#define in attribute\n" "#define out varying\n" "#endif\n" "uniform mat4 modelViewMatrix;\n" "uniform mat4 projectionMatrix;\n" "uniform vec4 color;\n" "in vec3 inPosition;\n" "out vec4 outColor;\n" "void main() {\n" " outColor = color;\n" " gl_Position = (projectionMatrix * modelViewMatrix) * vec4(inPosition, 1.0);\n" "}\n"; AttachShader(vertexShader, GL_VERTEX_SHADER, m_Program); static const char fragmentShader[] = "" "#if __VERSION__ < 130\n" "#define in varying\n" "#define outPixelColor gl_FragColor\n" "#else\n" "out vec4 outPixelColor;\n" "#endif\n" "in vec4 outColor;\n" "void main() {\n" " outPixelColor = outColor;\n" "}\n" ; AttachShader(fragmentShader, GL_FRAGMENT_SHADER, m_Program); glBindAttribLocation(m_Program, 0, "inPosition"); glLinkProgram(m_Program); #ifndef NDEBUG { GLint compiled, len; glGetProgramiv(m_Program, GL_LINK_STATUS, &compiled); if (!compiled) { glGetProgramiv(m_Program, GL_INFO_LOG_LENGTH, &len); if (len > 0) { char *message = new char[len]; glGetProgramInfoLog(m_Program, len, &len, message); fprintf(stderr, "shader: %s", message); delete[] message; } } } #endif m_ColorUniform = glGetUniformLocation(m_Program, "color"); m_ModelviewMatrixUniform = glGetUniformLocation(m_Program, "modelViewMatrix"); m_ProjectionMatrixUniform = glGetUniformLocation(m_Program, "projectionMatrix"); } }
ShaderObject::ShaderObject( std::string VertexShaderFileName, std::string PixelShaderFileName ) { Handle = glCreateProgramObjectARB(); Compiled = false; ShaderCode VertexShader; ShaderCode PixelShader; VertexShader.CreateFromFile( VertexShaderFileName, GL_VERTEX_SHADER_ARB ); PixelShader.CreateFromFile( PixelShaderFileName, GL_FRAGMENT_SHADER_ARB ); AttachShader( VertexShader ); AttachShader( PixelShader ); LinkProgram(); }
// Compiles a GL shader and attaches it to a program. Returns the shader ID if // successful, or 0 if not. static GrGLuint attach_shader(const GrGLContext& glCtx, GrGLuint programId, GrGLenum type, const SkString& shaderSrc) { const GrGLInterface* gli = glCtx.interface(); GrGLuint shaderId; GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); if (0 == shaderId) { return 0; } const GrGLchar* sourceStr = shaderSrc.c_str(); GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); GR_GL_CALL(gli, CompileShader(shaderId)); // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. bool checkCompiled = !glCtx.isChromium(); #ifdef SK_DEBUG checkCompiled = true; #endif if (checkCompiled) { GrGLint compiled = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); if (!compiled) { GrGLint infoLen = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { // retrieve length even though we don't need it to workaround bug in Chromium cmd // buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get())); GrPrintf(shaderSrc.c_str()); GrPrintf("\n%s", log.get()); } SkDEBUGFAIL("Shader compilation failed!"); GR_GL_CALL(gli, DeleteShader(shaderId)); return 0; } } TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader", TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shaderSrc.c_str())); if (c_PrintShaders) { GrPrintf(shaderSrc.c_str()); GrPrintf("\n"); } // Attach the shader, but defer deletion until after we have linked the program. // This works around a bug in the Android emulator's GLES2 wrapper which // will immediately delete the shader object and free its memory even though it's // attached to a program, which then causes glLinkProgram to fail. GR_GL_CALL(gli, AttachShader(programId, shaderId)); return shaderId; }
void AbstractShader<ShaderType::VERTEX_SHADER>::BuildShader(ID3D10Blob * shaderBlob) { ID3D11VertexShader * vertexShader; mDxgiInstance->mDevice->CreateVertexShader(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL, &vertexShader); AttachShader(vertexShader); }
void AbstractShader<ShaderType::PIXEL_SHADER>::BuildShader(ID3D10Blob * shaderBlob) { ID3D11PixelShader * pixelShader; mDxgiInstance->mDevice->CreatePixelShader(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL, &pixelShader); AttachShader(pixelShader); }
void Shader::LoadShader( const std::string &filename, int type ) { GLuint shaderID = glCreateShader( type ); std::string shaderCode; std::ifstream shaderStream( filename, std::ios::in ); if ( shaderStream.is_open() ) { std::string line = ""; while ( getline( shaderStream, line ) ) { shaderCode += "\n" + line; } shaderStream.close(); } else { fprintf( stderr, "Error loading shader." ); return; } GLint result = GL_FALSE; int infoLogLength; char const *sourcePoint = shaderCode.c_str(); glShaderSource( shaderID, 1, &sourcePoint, NULL ); glCompileShader( shaderID ); glGetShaderiv( shaderID, GL_COMPILE_STATUS, &result ); glGetShaderiv( shaderID, GL_INFO_LOG_LENGTH, &infoLogLength ); std::vector<char> shaderErrorMessage( infoLogLength ); glGetShaderInfoLog( shaderID, infoLogLength, NULL, &shaderErrorMessage[ 0 ] ); // fprintf( stdout, "%s\n", &shaderErrorMessage[ 0 ] ); AttachShader( shaderID ); }
Framework::OpenGl::ProgramPtr CGSH_OpenGL::GenerateShader(const SHADERCAPS& caps) { auto vertexShader = GenerateVertexShader(caps); auto fragmentShader = GenerateFragmentShader(caps); auto result = std::make_shared<Framework::OpenGl::CProgram>(); result->AttachShader(vertexShader); result->AttachShader(fragmentShader); bool linkResult = result->Link(); assert(linkResult); assert(glGetError() == GL_NO_ERROR); return result; }
void Mesh::AttachShader(string Vert, string Frag) { // Set shader sp = new ShaderProgram(Vert, Frag); if(!sp) { cerr << "Could not create shader program with sources \"" << Vert << "\" and \"" << Frag << "\"" << endl; AttachShader(); } }
// Compiles a GL shader, attaches it to a program, and releases the shader's reference. // (That way there's no need to hang on to the GL shader id and delete it later.) static bool attach_shader(const GrGLContext& glCtx, GrGLuint programId, GrGLenum type, const SkString& shaderSrc) { const GrGLInterface* gli = glCtx.interface(); GrGLuint shaderId; GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); if (0 == shaderId) { return false; } const GrGLchar* sourceStr = shaderSrc.c_str(); GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); GR_GL_CALL(gli, CompileShader(shaderId)); // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. bool checkCompiled = !glCtx.info().isChromium(); #ifdef SK_DEBUG checkCompiled = true; #endif if (checkCompiled) { GrGLint compiled = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); if (!compiled) { GrGLint infoLen = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { // retrieve length even though we don't need it to workaround bug in Chromium cmd // buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get())); GrPrintf(shaderSrc.c_str()); GrPrintf("\n%s", log.get()); } SkDEBUGFAIL("Shader compilation failed!"); GR_GL_CALL(gli, DeleteShader(shaderId)); return false; } } if (c_PrintShaders) { GrPrintf(shaderSrc.c_str()); GrPrintf("\n"); } GR_GL_CALL(gli, AttachShader(programId, shaderId)); GR_GL_CALL(gli, DeleteShader(shaderId)); return true; }
/* ============= OpenGLProgram::InitializeProgram OpenGLProgram Initialization. ============= */ bool OpenGLProgram::InitializeProgram( const char* name, const std::vector<Shader*>& shaderList, const char* outVariable, ProgramFeatures::Value features ) { m_programID = glCreateProgram(); SetProgramName( name ); for( std::vector<Shader*>::const_iterator iter = shaderList.begin(); iter != shaderList.end(); ++iter ) { if( AttachShader( ( *iter ) ) == 0 ) { char buff[256]; sprintf_s( buff, "Failed to compile %s program", name ); Log::GetInstance()->WriteToLog( "OpenGLProgram", buff ); return false; } } SetOutVariable( outVariable ); LinkProgram(); SetFeatures( features ); return m_programID > 0; }
void GLSLProgram::Create( char *vfile, char *gfile, char *ffile ) { CanDoFragmentShader = IsExtensionSupported( "GL_ARB_fragment_shader" ); CanDoGeometryShader = IsExtensionSupported( "GL_EXT_geometry_shader4" ); CanDoVertexShader = IsExtensionSupported( "GL_ARB_vertex_shader" ); InputTopology = GL_TRIANGLES; OutputTopology = GL_TRIANGLE_STRIP; Vshader = Gshader = Fshader = 0; Program = 0; AttributeLocs.clear(); UniformLocs.clear(); Verbose = false; this->Program = glCreateProgram(); CheckGlErrors( "glCreateProgram" ); if( vfile != NULL && vfile[0] != '\0' ) { if( ! CanDoVertexShader ) { fprintf( stderr, "Warning: this system cannot handle vertex shaders\n" ); } this->Vshader = LoadVertexShader( vfile ); int status = CompileShader( this->Vshader ); if( status != 0 ) { if( this->Verbose ) fprintf( stderr, "Shader '%s' compiled.\n", vfile ); AttachShader( this->Vshader ); } else { fprintf( stderr, "Shader '%s' did not compile.\n", vfile ); } } if( gfile != NULL && gfile[0] != '\0' ) { if( ! CanDoGeometryShader ) { fprintf( stderr, "Warning: this system cannot handle geometry shaders\n" ); } this->Gshader = LoadGeometryShader( gfile ); int status = CompileShader( this->Gshader ); if( status != 0 ) { if( this->Verbose ) fprintf( stderr, "Shader '%s' compiled.\n", gfile ); AttachShader( Gshader ); } else { fprintf( stderr, "Shader '%s' did not compile.\n", gfile ); } } if( ffile != NULL && ffile[0] != '\0' ) { if( ! CanDoFragmentShader ) { fprintf( stderr, "Warning: this system cannot handle fragment shaders\n" ); } this->Fshader = LoadFragmentShader( ffile ); int status = CompileShader( this->Fshader ); if( status != 0 ) { if( this->Verbose ) fprintf( stderr, "Shader '%s' compiled.\n", ffile ); AttachShader( Fshader ); } else { fprintf( stderr, "Shader '%s' did not compile.\n", ffile ); } } LinkProgram(); };
void GrGLProgram::genProgram(GrGLProgram::CachedData* programData, const GrDrawTarget* target) const { ShaderCodeSegments segments; const uint32_t& layout = fProgramDesc.fVertexLayout; memset(&programData->fUniLocations, 0, sizeof(UniLocations)); bool haveColor = !(ProgramDesc::kVertexColorAllOnes_OptFlagBit & fProgramDesc.fOptFlags); #if ATTRIBUTE_MATRIX segments.fVSAttrs = "attribute mat3 " VIEW_MATRIX_NAME ";\n"; #else segments.fVSUnis = "uniform mat3 " VIEW_MATRIX_NAME ";\n"; segments.fVSAttrs = ""; #endif segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n"; if (haveColor) { segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n"; segments.fVaryings = "varying vec4 vColor;\n"; } else { segments.fVaryings = ""; } segments.fVSCode = "void main() {\n" "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n" "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n"; if (haveColor) { segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n"; } if (!(fProgramDesc.fOptFlags & ProgramDesc::kNotPoints_OptFlagBit)) { segments.fVSCode += "\tgl_PointSize = 1.0;\n"; } segments.fFSCode = "void main() {\n"; // add texture coordinates that are used to the list of vertex attr decls GrTokenString texCoordAttrs[GrDrawTarget::kMaxTexCoords]; for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) { if (target->VertexUsesTexCoordIdx(t, layout)) { tex_attr_name(t, texCoordAttrs + t); segments.fVSAttrs += "attribute vec2 "; segments.fVSAttrs += texCoordAttrs[t]; segments.fVSAttrs += ";\n"; } } // for each enabled stage figure out what the input coordinates are // and count the number of stages in use. const char* stageInCoords[GrDrawTarget::kNumStages]; int numActiveStages = 0; for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { if (fProgramDesc.fStages[s].fEnabled) { if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) { stageInCoords[s] = POS_ATTR_NAME; } else { int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout); // we better have input tex coordinates if stage is enabled. GrAssert(tcIdx >= 0); GrAssert(texCoordAttrs[tcIdx].length()); stageInCoords[s] = texCoordAttrs[tcIdx].cstr(); } ++numActiveStages; } } GrTokenString inColor = "vColor"; // if we have active stages string them together, feeding the output color // of each to the next and generating code for each stage. if (numActiveStages) { int currActiveStage = 0; for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { if (fProgramDesc.fStages[s].fEnabled) { GrTokenString outColor; if (currActiveStage < (numActiveStages - 1)) { outColor = "color"; outColor.appendInt(currActiveStage); segments.fFSCode += "\tvec4 "; segments.fFSCode += outColor; segments.fFSCode += ";\n"; } else { outColor = "gl_FragColor"; } genStageCode(s, fProgramDesc.fStages[s], haveColor ? inColor.cstr() : NULL, outColor.cstr(), stageInCoords[s], &segments, &programData->fUniLocations.fStages[s]); ++currActiveStage; inColor = outColor; haveColor = true; } } } else { segments.fFSCode += "\tgl_FragColor = "; if (haveColor) { segments.fFSCode += inColor; } else { segments.fFSCode += "vec4(1,1,1,1)"; } segments.fFSCode += ";\n"; } segments.fFSCode += "}\n"; segments.fVSCode += "}\n"; const char* strings[4]; int lengths[4]; int stringCnt = 0; if (segments.fVSUnis.length()) { strings[stringCnt] = segments.fVSUnis.cstr(); lengths[stringCnt] = segments.fVSUnis.length(); ++stringCnt; } if (segments.fVSAttrs.length()) { strings[stringCnt] = segments.fVSAttrs.cstr(); lengths[stringCnt] = segments.fVSAttrs.length(); ++stringCnt; } if (segments.fVaryings.length()) { strings[stringCnt] = segments.fVaryings.cstr(); lengths[stringCnt] = segments.fVaryings.length(); ++stringCnt; } GrAssert(segments.fVSCode.length()); strings[stringCnt] = segments.fVSCode.cstr(); lengths[stringCnt] = segments.fVSCode.length(); ++stringCnt; #if PRINT_SHADERS GrPrintf("%s%s%s%s\n", segments.fVSUnis.cstr(), segments.fVSAttrs.cstr(), segments.fVaryings.cstr(), segments.fVSCode.cstr()); #endif programData->fVShaderID = CompileShader(GR_GL_VERTEX_SHADER, stringCnt, strings, lengths); stringCnt = 0; if (strlen(GrShaderPrecision()) > 1) { strings[stringCnt] = GrShaderPrecision(); lengths[stringCnt] = strlen(GrShaderPrecision()); ++stringCnt; } if (segments.fFSUnis.length()) { strings[stringCnt] = segments.fFSUnis.cstr(); lengths[stringCnt] = segments.fFSUnis.length(); ++stringCnt; } if (segments.fVaryings.length()) { strings[stringCnt] = segments.fVaryings.cstr(); lengths[stringCnt] = segments.fVaryings.length(); ++stringCnt; } GrAssert(segments.fFSCode.length()); strings[stringCnt] = segments.fFSCode.cstr(); lengths[stringCnt] = segments.fFSCode.length(); ++stringCnt; #if PRINT_SHADERS GrPrintf("%s%s%s%s\n", GR_SHADER_PRECISION, segments.fFSUnis.cstr(), segments.fVaryings.cstr(), segments.fFSCode.cstr()); #endif programData->fFShaderID = CompileShader(GR_GL_FRAGMENT_SHADER, stringCnt, strings, lengths); programData->fProgramID = GR_GL(CreateProgram()); const GrGLint& progID = programData->fProgramID; GR_GL(AttachShader(progID, programData->fVShaderID)); GR_GL(AttachShader(progID, programData->fFShaderID)); // Bind the attrib locations to same values for all shaders GR_GL(BindAttribLocation(progID, POS_ATTR_LOCATION, POS_ATTR_NAME)); for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) { if (texCoordAttrs[t].length()) { GR_GL(BindAttribLocation(progID, TEX_ATTR_LOCATION(t), texCoordAttrs[t].cstr())); } } #if ATTRIBUTE_MATRIX // set unis to a bogus value so that checks against -1 before // flushing will pass. GR_GL(BindAttribLocation(progID, VIEWMAT_ATTR_LOCATION, VIEW_MATRIX_NAME)); program->fUniLocations.fViewMatrixUni = BOGUS_MATRIX_UNI_LOCATION; for (int s = 0; s < kNumStages; ++s) { if (fProgramDesc.fStages[s].fEnabled) { GrStringBuilder matName; tex_matrix_name(s, &matName); GR_GL(BindAttribLocation(progID, TEXMAT_ATTR_LOCATION(s), matName.cstr())); program->fUniLocations.fStages[s].fTextureMatrixUni = BOGUS_MATRIX_UNI_LOCATION; } } #endif GR_GL(BindAttribLocation(progID, COL_ATTR_LOCATION, COL_ATTR_NAME)); GR_GL(LinkProgram(progID)); GrGLint linked = GR_GL_INIT_ZERO; GR_GL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked)); if (!linked) { GrGLint infoLen = GR_GL_INIT_ZERO; GR_GL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen)); GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { GR_GL(GetProgramInfoLog(progID, infoLen+1, NULL, (char*)log.get())); GrPrintf((char*)log.get()); } GrAssert(!"Error linking program"); GR_GL(DeleteProgram(progID)); programData->fProgramID = 0; return; } // Get uniform locations #if !ATTRIBUTE_MATRIX programData->fUniLocations.fViewMatrixUni = GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME)); GrAssert(-1 != programData->fUniLocations.fViewMatrixUni); #endif for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { StageUniLocations& locations = programData->fUniLocations.fStages[s]; if (fProgramDesc.fStages[s].fEnabled) { #if !ATTRIBUTE_MATRIX if (locations.fTextureMatrixUni) { GrTokenString texMName; tex_matrix_name(s, &texMName); locations.fTextureMatrixUni = GR_GL(GetUniformLocation( progID, texMName.cstr())); GrAssert(-1 != locations.fTextureMatrixUni); } else { locations.fTextureMatrixUni = -1; } #endif if (locations.fSamplerUni) { GrTokenString samplerName; sampler_name(s, &samplerName); locations.fSamplerUni = GR_GL(GetUniformLocation( progID, samplerName.cstr())); GrAssert(-1 != locations.fSamplerUni); } else { locations.fSamplerUni = -1; } if (locations.fRadial2Uni) { GrTokenString radial2ParamName; radial2_param_name(s, &radial2ParamName); locations.fRadial2Uni = GR_GL(GetUniformLocation( progID, radial2ParamName.cstr())); GrAssert(-1 != locations.fRadial2Uni); } else { locations.fRadial2Uni = -1; } } else { locations.fSamplerUni = -1; locations.fRadial2Uni = -1; locations.fTextureMatrixUni = -1; } } GR_GL(UseProgram(progID)); // init sampler unis and set bogus values for state tracking for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { if (-1 != programData->fUniLocations.fStages[s].fSamplerUni) { GR_GL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s)); } programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix(); programData->fRadial2CenterX1[s] = GR_ScalarMax; programData->fRadial2Radius0[s] = -GR_ScalarMax; } programData->fViewMatrix = GrMatrix::InvalidMatrix(); }
static GrGLuint compile_shader(const GrGLContext* ctx) { const char* version = GrGLGetGLSLVersionDecl(*ctx); // setup vertex shader GrGLShaderVar aPosition("a_position", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier); GrGLShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kAttribute_TypeModifier); GrGLShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kVaryingOut_TypeModifier); SkString vshaderTxt(version); aPosition.appendDecl(*ctx, &vshaderTxt); vshaderTxt.append(";\n"); aColor.appendDecl(*ctx, &vshaderTxt); vshaderTxt.append(";\n"); oColor.appendDecl(*ctx, &vshaderTxt); vshaderTxt.append(";\n"); vshaderTxt.append( "void main()\n" "{\n" "gl_Position = vec4(a_position, 0.f, 1.f);\n" "o_color = a_color;\n" "}\n"); const GrGLInterface* gl = ctx->interface(); GrGLuint vertexShader = load_shader(gl, vshaderTxt.c_str(), GR_GL_VERTEX_SHADER); // setup fragment shader GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier); SkString fshaderTxt(version); GrGLAppendGLSLDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, gl->fStandard, &fshaderTxt); oColor.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier); oColor.appendDecl(*ctx, &fshaderTxt); fshaderTxt.append(";\n"); const char* fsOutName; if (ctx->caps()->glslCaps()->mustDeclareFragmentShaderOutput()) { oFragColor.appendDecl(*ctx, &fshaderTxt); fshaderTxt.append(";\n"); fsOutName = oFragColor.c_str(); } else { fsOutName = "gl_FragColor"; } fshaderTxt.appendf( "void main()\n" "{\n" "%s = vec4(o_color, 1.0f);\n" "}\n", fsOutName); GrGLuint fragmentShader = load_shader(gl, fshaderTxt.c_str(), GR_GL_FRAGMENT_SHADER); GrGLint shaderProgram; GR_GL_CALL_RET(gl, shaderProgram, CreateProgram()); GR_GL_CALL(gl, AttachShader(shaderProgram, vertexShader)); GR_GL_CALL(gl, AttachShader(shaderProgram, fragmentShader)); GR_GL_CALL(gl, LinkProgram(shaderProgram)); // Check for linking errors GrGLint success; GrGLchar infoLog[512]; GR_GL_CALL(gl, GetProgramiv(shaderProgram, GR_GL_LINK_STATUS, &success)); if (!success) { GR_GL_CALL(gl, GetProgramInfoLog(shaderProgram, 512, NULL, infoLog)); SkDebugf("Linker Error: %s\n", infoLog); } GR_GL_CALL(gl, DeleteShader(vertexShader)); GR_GL_CALL(gl, DeleteShader(fragmentShader)); return shaderProgram; }
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader) { CONTEXT_EXEC(AttachShader(program, shader)); }
RippleTexProg(GLuint ripple_tex_size) : tex_1(prog(), "Tex1") , tex_2(prog(), "Tex2") , new_drop(prog(), "NewDrop") { AttachShader(VertexShader( ObjectDesc("Ripple texture vertex shader"), StrLit( "#version 330\n" "void main(void)" "{" " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);" "}" ) )); AttachShader(GeometryShader( ObjectDesc("Ripple texture geometry shader"), StrLit( "#version 330\n" "layout (points) in;" "layout (triangle_strip, max_vertices = 4) out;" "uniform int TexSize;" "out vec2 geomTexCoord;" "void make_vertex(vec2 pos, vec2 tc)" "{" " gl_Position = vec4(pos, 0.0, 1.0);" " geomTexCoord = tc;" " EmitVertex();" "}" "void main(void)" "{" " float rts = TexSize;" " make_vertex(vec2(-1.0,-1.0), vec2( 0, 0));" " make_vertex(vec2(-1.0, 1.0), vec2( 0, rts));" " make_vertex(vec2( 1.0,-1.0), vec2(rts, 0));" " make_vertex(vec2( 1.0, 1.0), vec2(rts, rts));" " EndPrimitive();" "}" ) )); AttachShader(FragmentShader( ObjectDesc("Ripple texture fragment shader"), StrLit( "#version 330\n" "uniform ivec2 NewDrop;" "uniform sampler2D Tex1, Tex2;" "uniform int TexSize;" "in vec2 geomTexCoord;" "layout (location = 0) out vec4 fragBump;" "layout (location = 1) out float fragHeight;" "ivec2 wrap_tc(ivec2 tc)" "{" " if(tc.x < 0) tc.x = TexSize-1;" " if(tc.x >= TexSize) tc.x = 0;" " if(tc.y < 0) tc.y = TexSize-1;" " if(tc.y >= TexSize) tc.y = 0;" " return tc;" "}" "float height_at(sampler2D tex, ivec2 tc, float factor)" "{" " return texelFetch(tex, wrap_tc(tc), 0).r * factor;" "}" "void main(void)" "{" " ivec2 TC = ivec2(geomTexCoord);" " float ch = height_at(Tex2, TC, 1.0);" " float xp1 = height_at(Tex2, TC+ivec2( 1, 0), 0.25);" " float xm1 = height_at(Tex2, TC+ivec2(-1, 0), 0.25);" " float yp1 = height_at(Tex2, TC+ivec2( 0, 1), 0.25);" " float ym1 = height_at(Tex2, TC+ivec2( 0,-1), 0.25);" " fragHeight = xp1 + xm1 + yp1 + ym1;" " fragHeight += height_at(Tex2, TC+ivec2( 1,-1), 0.25);" " fragHeight += height_at(Tex2, TC+ivec2( 1, 1), 0.25);" " fragHeight += height_at(Tex2, TC+ivec2(-1,-1), 0.25);" " fragHeight += height_at(Tex2, TC+ivec2(-1, 1), 0.25);" " fragHeight -= height_at(Tex1, TC, 1.0);" " vec2 d = NewDrop - TC;" " fragHeight += length(d)<8?1.0:0.0;" " vec3 fragNormal = vec3(" " (xm1 - ch) + (ch - xp1)," " (ym1 - ch) + (ch - yp1)," " 0.1" " );" " fragBump = vec4(" " normalize(fragNormal)," " fragHeight" " );" "}" ) )); Link(); ProgramUniform<GLint>(prog(), "TexSize").Set(ripple_tex_size); }
WaterProg(void) : projection_matrix(prog(), "ProjectionMatrix") , camera_matrix(prog(), "CameraMatrix") , camera_position(prog(), "CameraPosition") , light_position(prog(), "LightPosition") , ripple_tex(prog(), "RippleTex") , env_tex(prog(), "EnvTex") { AttachShader(VertexShader( ObjectDesc("Water vertex shader"), StrLit( "#version 330\n" "uniform mat4 ProjectionMatrix, CameraMatrix;" "uniform vec3 LightPosition, CameraPosition;" "mat4 Matrix = ProjectionMatrix*CameraMatrix;" "in vec3 Position;" "in vec3 Normal;" "in vec3 Tangent;" "in vec2 TexCoord;" "out vec3 vertNormal, vertTangent, vertBitangent;" "out vec3 vertLightDir, vertViewDir;" "out vec2 vertTexCoord;" "void main(void)" "{" " gl_Position = Matrix * vec4(Position, 1.0);" " vertNormal = Normal;" " vertTangent = Tangent;" " vertBitangent = cross(Normal, Tangent);" " vertLightDir = LightPosition - Position;" " vertViewDir = CameraPosition - Position;" " vertTexCoord = TexCoord * 16.0;" "}" ) )); AttachShader(FragmentShader( ObjectDesc("Water fragment shader"), StrLit( "#version 330\n" "uniform sampler2D RippleTex;" "uniform samplerCube EnvTex;" "in vec3 vertNormal, vertTangent, vertBitangent;" "in vec3 vertLightDir, vertViewDir;" "in vec2 vertTexCoord;" "layout (location = 0) out vec4 fragColor;" "const vec3 LightColor = vec3(1.0, 1.0, 0.95);" "const vec3 BgColor = vec3(0.4, 0.4, 0.4);" "void main(void)" "{" " vec4 texBump = texture(RippleTex, vertTexCoord);" " vec3 fragNormal = normalize(" " texBump.x * vertTangent+" " texBump.y * vertBitangent+" " texBump.z * vertNormal" " );" " vec3 fragLightDir = normalize(vertLightDir);" " vec3 fragLightRefl = reflect(-fragLightDir, fragNormal);" " vec3 fragViewDir = normalize(vertViewDir);" " vec3 fragViewRefl = reflect(-fragViewDir, fragNormal);" " vec3 fragViewRefr = refract(" " -normalize(fragViewDir+vec3(0.0, 1.0, 0.0))," " fragNormal," " 1.2" " );" " float Diffuse = max(dot(fragNormal, fragLightDir), 0.0);" " float Specular = clamp(pow(dot(fragViewDir, fragLightRefl)+0.1, 64.0), 0.0, 2.0);" " float Transparency = max(dot(fragNormal, fragViewDir)+0.3, 0.0);" " float Visibility = min(16.0 / dot(vertViewDir, vertViewDir), 1.0);" " vec3 SkyColor = texture(EnvTex, fragViewRefl).rgb;" " vec3 GroundColor = texture(EnvTex, fragViewRefr).rgb;" " vec3 WaterColor = " " mix(" " 0.7*SkyColor," " 0.8*GroundColor*LightColor*Diffuse," " Transparency" " )+" " 0.2*LightColor*Diffuse+" " 0.05*LightColor*Specular;" " fragColor = vec4(" " mix(BgColor, WaterColor, Visibility)," " 1.0" " );" "}" ) )); Link(); }
ShaderProgram& AttachShaders(ShaderFile *shader, Rest&&... rest) { AttachShader(shader); AttachShaders(rest...); return *this; }