bool GrGLShaderBuilder::finish() { SkASSERT(0 == fOutput.fProgramID); GL_CALL_RET(fOutput.fProgramID, CreateProgram()); if (!fOutput.fProgramID) { return false; } SkTDArray<GrGLuint> shadersToDelete; if (!this->compileAndAttachShaders(fOutput.fProgramID, &shadersToDelete)) { GL_CALL(DeleteProgram(fOutput.fProgramID)); return false; } this->bindProgramLocations(fOutput.fProgramID); if (fUniformManager->isUsingBindUniform()) { fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms); } GL_CALL(LinkProgram(fOutput.fProgramID)); // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. bool checkLinked = !fGpu->ctxInfo().isChromium(); #ifdef SK_DEBUG checkLinked = true; #endif if (checkLinked) { GrGLint linked = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(fOutput.fProgramID, GR_GL_LINK_STATUS, &linked)); if (!linked) { GrGLint infoLen = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(fOutput.fProgramID, 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 chrome cmd buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GL_CALL(GetProgramInfoLog(fOutput.fProgramID, infoLen+1, &length, (char*)log.get())); GrPrintf((char*)log.get()); } SkDEBUGFAIL("Error linking program"); GL_CALL(DeleteProgram(fOutput.fProgramID)); fOutput.fProgramID = 0; return false; } } if (!fUniformManager->isUsingBindUniform()) { fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms); } for (int i = 0; i < shadersToDelete.count(); ++i) { GL_CALL(DeleteShader(shadersToDelete[i])); } return true; }
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; }
bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) { SK_TRACE_EVENT0("GrGLShaderBuilder::finish"); GrGLuint programId = 0; GL_CALL_RET(programId, CreateProgram()); if (!programId) { return false; } if (!this->compileAndAttachShaders(programId)) { GL_CALL(DeleteProgram(programId)); return false; } this->bindProgramLocations(programId); GL_CALL(LinkProgram(programId)); // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. bool checkLinked = !fGpu->ctxInfo().isChromium(); #ifdef SK_DEBUG checkLinked = true; #endif if (checkLinked) { GrGLint linked = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programId, GR_GL_LINK_STATUS, &linked)); if (!linked) { GrGLint infoLen = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programId, 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 chrome cmd buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GL_CALL(GetProgramInfoLog(programId, infoLen+1, &length, (char*)log.get())); GrPrintf((char*)log.get()); } SkDEBUGFAIL("Error linking program"); GL_CALL(DeleteProgram(programId)); return false; } } fUniformManager.getUniformLocations(programId, fUniforms); *outProgramId = programId; return true; }
GLboolean ValidateShaderProgram(GLuint program) { GLint stat; ValidateProgram(program); GetProgramiv(program, GL_VALIDATE_STATUS, &stat); if (!stat) { GLchar log[1000]; GLsizei len; GetProgramInfoLog(program, 1000, &len, log); wxLogError(wxT("BR24radar_pi: program validation error: %s"), log); return 0; } return (GLboolean)stat; }
inline GLuint CreateProgram(LPCSTR vsrc, LPCSTR fsrc) { const GLuint vobj = glCreateShader(GL_VERTEX_SHADER); if (!vobj) return 0; glShaderSource(vobj, 1, &vsrc, 0); glCompileShader(vobj); if (GetShaderInfoLog(vobj) == 0) { glDeleteShader(vobj); return 0; } const GLuint fobj = glCreateShader(GL_FRAGMENT_SHADER); if (!fobj) { glDeleteShader(vobj); return 0; } glShaderSource(fobj, 1, &fsrc, 0); glCompileShader(fobj); if (GetShaderInfoLog(fobj) == 0) { glDeleteShader(vobj); glDeleteShader(fobj); return 0; } GLuint program = glCreateProgram(); if (program) { glAttachShader(program, vobj); glAttachShader(program, fobj); glLinkProgram(program); if (GetProgramInfoLog(program) == 0) { glDetachShader(program, fobj); glDetachShader(program, vobj); glDeleteProgram(program); program = 0; } } glDeleteShader(vobj); glDeleteShader(fobj); return program; }
bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) { GrGLint linked = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked)); if (!linked) { SkDebugf("Program linking failed.\n"); GrGLint infoLen = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programID, 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 chrome cmd buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GL_CALL(GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get())); SkDebugf("%s", (char*)log.get()); } GL_CALL(DeleteProgram(programID)); programID = 0; } return SkToBool(linked); }
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; }
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 void Init(void) { static const char *fragShaderText = "uniform float StipplePattern[16]; \n" "varying float stippleCoord; \n" "void main() \n" "{ \n" " // check the stipple pattern and discard if value is zero \n" " // TODO: we should really undo the perspective interpolation here \n" " // so that it's linear. \n" " float stip = StipplePattern[int(fract(stippleCoord) * 16.0)]; \n" " if (stip == 0.0) \n" " discard; \n" " gl_FragColor = gl_Color; \n" "} \n"; static const char *vertShaderText = "void main() \n" "{ \n" " gl_FrontColor = gl_Color; \n" " gl_Position = ftransform(); \n" "} \n"; static const char *geomShaderText = "#version 120 \n" "#extension GL_ARB_geometry_shader4: enable \n" "uniform vec2 ViewportSize; \n" "uniform float StippleFactor; \n" "varying float stippleCoord; \n" "void main() \n" "{ \n" " vec4 pos0 = gl_PositionIn[0]; \n" " vec4 pos1 = gl_PositionIn[1]; \n" " // Convert eye coords to window coords \n" " // Note: we're off by a factor of two here, make up for that below \n" " vec2 p0 = pos0.xy / pos0.w * ViewportSize; \n" " vec2 p1 = pos1.xy / pos1.w * ViewportSize; \n" " float len = length(p0.xy - p1.xy); \n" " // Emit first vertex \n" " gl_FrontColor = gl_FrontColorIn[0]; \n" " gl_Position = pos0; \n" " stippleCoord = 0.0; \n" " EmitVertex(); \n" " // Emit second vertex \n" " gl_FrontColor = gl_FrontColorIn[1]; \n" " gl_Position = pos1; \n" " stippleCoord = len / StippleFactor / 32.0; // Note: not 16, see above \n" " EmitVertex(); \n" "} \n"; if (!ShadersSupported()) exit(1); if (!glutExtensionSupported("GL_ARB_geometry_shader4")) { fprintf(stderr, "Sorry, GL_ARB_geometry_shader4 is not supported.\n"); exit(1); } VertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText); FragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText); GeomShader = CompileShaderText(GL_GEOMETRY_SHADER_ARB, geomShaderText); assert(GeomShader); Program = LinkShaders3(VertShader, GeomShader, FragShader); assert(Program); CheckError(__LINE__); /* * The geometry shader accepts lines and produces lines. */ glProgramParameteriARB(Program, GL_GEOMETRY_INPUT_TYPE_ARB, GL_LINES); glProgramParameteriARB(Program, GL_GEOMETRY_OUTPUT_TYPE_ARB, GL_LINE_STRIP); glProgramParameteriARB(Program, GL_GEOMETRY_VERTICES_OUT_ARB, 4); CheckError(__LINE__); glLinkProgramARB(Program); /* check link */ { GLint stat; GetProgramiv(Program, GL_LINK_STATUS, &stat); if (!stat) { GLchar log[1000]; GLsizei len; GetProgramInfoLog(Program, 1000, &len, log); fprintf(stderr, "Shader link error:\n%s\n", log); } } glUseProgram(Program); uViewportSize = glGetUniformLocation(Program, "ViewportSize"); uStippleFactor = glGetUniformLocation(Program, "StippleFactor"); uStipplePattern = glGetUniformLocation(Program, "StipplePattern"); glUniform1f(uStippleFactor, StippleFactor); glClearColor(0.3f, 0.3f, 0.3f, 0.0f); printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); assert(glIsProgram(Program)); assert(glIsShader(FragShader)); assert(glIsShader(VertShader)); assert(glIsShader(GeomShader)); glLineStipple(StippleFactor, StipplePattern); SetStippleUniform(StippleFactor, StipplePattern); MakePointsVBO(); }
static void Init(void) { static const char *fragShaderText = "void main() \n" "{ \n" " gl_FragColor = gl_Color; \n" "} \n"; static const char *vertShaderText = "void main() \n" "{ \n" " gl_FrontColor = gl_Color; \n" " gl_Position = ftransform(); \n" "} \n"; static const char *geomShaderText = "#version 120 \n" "#extension GL_ARB_geometry_shader4: enable \n" "uniform vec2 InverseViewportSize; \n" "uniform float LineWidth; \n" "void main() \n" "{ \n" " vec4 pos0 = gl_PositionIn[0]; \n" " vec4 pos1 = gl_PositionIn[1]; \n" " vec4 dir = abs(pos1 - pos0); \n" " vec2 d0 = vec2(LineWidth * pos0.w) * InverseViewportSize; \n" " vec2 d1 = vec2(LineWidth * pos1.w) * InverseViewportSize; \n" " // this conditional could be avoided \n" " if (dir.x > dir.y) { \n" " // X-major line \n" " d0.x = 0.0; \n" " d1.x = 0.0; \n" " } \n" " else { \n" " // Y-major line \n" " d0.y = 0.0; \n" " d1.y = 0.0; \n" " } \n" " gl_FrontColor = gl_FrontColorIn[0]; \n" " gl_TexCoord[0] = vec4(0, 0, 0, 1); \n" " gl_Position = pos0 + vec4( d0.x, -d0.y, 0, 0); \n" " EmitVertex(); \n" " gl_FrontColor = gl_FrontColorIn[1]; \n" " gl_TexCoord[0] = vec4(1, 0, 0, 1); \n" " gl_Position = pos1 + vec4( d1.x, -d1.y, 0, 0); \n" " EmitVertex(); \n" " gl_FrontColor = gl_FrontColorIn[0]; \n" " gl_TexCoord[0] = vec4(0, 1, 0, 1); \n" " gl_Position = pos0 + vec4(-d0.x, d0.y, 0, 0); \n" " EmitVertex(); \n" " gl_FrontColor = gl_FrontColorIn[1]; \n" " gl_TexCoord[0] = vec4(1, 1, 0, 1); \n" " gl_Position = pos1 + vec4(-d1.x, d1.y, 0, 0); \n" " EmitVertex(); \n" "} \n"; if (!ShadersSupported()) exit(1); if (!glutExtensionSupported("GL_ARB_geometry_shader4")) { fprintf(stderr, "Sorry, GL_ARB_geometry_shader4 is not supported.\n"); exit(1); } VertShader = CompileShaderText(GL_VERTEX_SHADER, vertShaderText); FragShader = CompileShaderText(GL_FRAGMENT_SHADER, fragShaderText); GeomShader = CompileShaderText(GL_GEOMETRY_SHADER_ARB, geomShaderText); assert(GeomShader); Program = LinkShaders3(VertShader, GeomShader, FragShader); assert(Program); CheckError(__LINE__); /* * The geometry shader will convert incoming lines to quads (4-vertex * triangle strips). */ glProgramParameteriARB(Program, GL_GEOMETRY_INPUT_TYPE_ARB, GL_LINES); glProgramParameteriARB(Program, GL_GEOMETRY_OUTPUT_TYPE_ARB, GL_TRIANGLE_STRIP); glProgramParameteriARB(Program,GL_GEOMETRY_VERTICES_OUT_ARB, 4); CheckError(__LINE__); glLinkProgramARB(Program); /* check link */ { GLint stat; GetProgramiv(Program, GL_LINK_STATUS, &stat); if (!stat) { GLchar log[1000]; GLsizei len; GetProgramInfoLog(Program, 1000, &len, log); fprintf(stderr, "Shader link error:\n%s\n", log); } } CheckError(__LINE__); glUseProgram(Program); CheckError(__LINE__); uInverseViewportSize = glGetUniformLocation(Program, "InverseViewportSize"); uLineWidth = glGetUniformLocation(Program, "LineWidth"); glClearColor(0.3f, 0.3f, 0.3f, 0.0f); printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER)); assert(glIsProgram(Program)); assert(glIsShader(FragShader)); assert(glIsShader(VertShader)); assert(glIsShader(GeomShader)); glEnable(GL_DEPTH_TEST); { GLfloat r[2]; glGetFloatv(GL_LINE_WIDTH_RANGE, r); MaxLineWidth = r[1]; } MakePointsVBO(); }