You've already forked lazarus-ccr
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2249 8e941d3f-bd1b-0410-a28a-d453659cc2b4
233 lines
5.8 KiB
ObjectPascal
233 lines
5.8 KiB
ObjectPascal
//
|
|
// Utility functions for compiling shaders and programs
|
|
//
|
|
// Author: Evan Hart
|
|
// Copyright (c) NVIDIA Corporation. All rights reserved.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
unit nvShaderUtils;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
{ $define NV_REPORT_COMPILE_ERRORS}
|
|
|
|
uses
|
|
Classes, SysUtils, GL, GLext;
|
|
|
|
function CompileGLSLShader(target: GLenum; shader: string): GLuint;
|
|
function CompileGLSLShaderFromFile(target: GLenum; filename: string): GLuint;
|
|
function LinkGLSLProgram(vertexShader: GLuint; fragmentShader: GLuint): GLuint;
|
|
function LinkGLSLProgram(vertexShader: GLuint; geometryShader: GLuint; inputType: GLint; vertexOut: GLint; outputType: GLint; fragmentShader: GLuint): GLuint;
|
|
function CompileASMShader(program_type: GLenum; code: string): GLuint;
|
|
function CompileASMShaderFromFile(target: GLenum; filename: string): GLuint;
|
|
|
|
implementation
|
|
|
|
function CompileGLSLShader(target: GLenum; shader: string): GLuint;
|
|
var
|
|
_object: GLuint;
|
|
compiled: GLint;
|
|
{$ifdef NV_REPORT_COMPILE_ERRORS}
|
|
temp: string;
|
|
{$endif}
|
|
begin
|
|
_object := glCreateShader(target);
|
|
if _object = 0 then
|
|
begin
|
|
Result := _object;
|
|
exit;
|
|
end;
|
|
|
|
glShaderSource(_object, 1, @shader, nil);
|
|
|
|
glCompileShader(_object);
|
|
|
|
//check if shader compiled
|
|
compiled := 0;
|
|
glGetShaderiv(_object, GL_COMPILE_STATUS, @compiled);
|
|
|
|
if compiled = 0 then
|
|
begin
|
|
{$ifdef NV_REPORT_COMPILE_ERRORS}
|
|
temp := '';
|
|
glGetShaderInfoLog(_object, 256, nil, @temp[1]);
|
|
writeln(stderr, 'Compile failed:');
|
|
writeln(stderr, temp);
|
|
{$endif}
|
|
glDeleteShader(_object);
|
|
|
|
Result := 0;
|
|
exit;
|
|
end;
|
|
|
|
Result := _object;
|
|
end;
|
|
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
function CompileGLSLShaderFromFile(target: GLenum; filename: string): GLuint;
|
|
var
|
|
_object: GLuint;
|
|
s: TStrings;
|
|
begin
|
|
//must read files as binary to prevent problems from newline translation
|
|
try
|
|
try
|
|
s := TStringList.Create;
|
|
s.LoadFromFile(filename);
|
|
|
|
_object := CompileGLSLShader(target, s.Text);
|
|
Result := _object;
|
|
exit;
|
|
finally
|
|
FreeAndNil(s);
|
|
end;
|
|
except
|
|
Result := 0;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
// Create a program composed of vertex and fragment shaders.
|
|
function LinkGLSLProgram(vertexShader: GLuint; fragmentShader: GLuint): GLuint;
|
|
var
|
|
_program: GLuint;
|
|
{$ifdef NV_REPORT_COMPILE_ERRORS}
|
|
infoLogLength: GLint;
|
|
infoLog: string;
|
|
charsWritten: GLint;
|
|
{$endif}
|
|
linkSucceed: GLint;
|
|
begin
|
|
_program := glCreateProgram();
|
|
glAttachShader(_program, vertexShader);
|
|
glAttachShader(_program, fragmentShader);
|
|
glLinkProgram(_program);
|
|
|
|
{$ifdef NV_REPORT_COMPILE_ERRORS}
|
|
// Get error log.
|
|
glGetProgramiv(_program, GL_INFO_LOG_LENGTH, @infoLogLength);
|
|
|
|
infoLog := StringOfChar(' ',infoLogLength);
|
|
glGetProgramInfoLog(_program, infoLogLength, @charsWritten, @infoLog[1]);
|
|
writeln(stdout, infoLog);
|
|
{$endif}
|
|
|
|
// Test linker result.
|
|
linkSucceed := GL_FALSE;
|
|
glGetProgramiv(_program, GL_LINK_STATUS, @linkSucceed);
|
|
if linkSucceed = GL_FALSE then
|
|
begin
|
|
glDeleteProgram(_program);
|
|
Result := 0;
|
|
exit;
|
|
end;
|
|
|
|
Result := _program;
|
|
end;
|
|
|
|
// Create a program composed of vertex, geometry and fragment shaders.
|
|
function LinkGLSLProgram(vertexShader: GLuint; geometryShader: GLuint; inputType: GLint; vertexOut: GLint; outputType: GLint; fragmentShader: GLuint): GLuint;
|
|
var
|
|
_program: GLuint;
|
|
{$ifdef NV_REPORT_COMPILE_ERRORS}
|
|
charsWritten: GLint;
|
|
infoLogLength: GLint;
|
|
infoLog: string;
|
|
{$endif}
|
|
linkSucceed: GLint;
|
|
begin
|
|
_program := glCreateProgram();
|
|
glAttachShader(_program, vertexShader);
|
|
glAttachShader(_program, geometryShader);
|
|
|
|
{$note fix this}
|
|
//glProgramParameteriEXT(_program,GL_GEOMETRY_INPUT_TYPE_EXT,inputType);
|
|
//glProgramParameteriEXT(_program,GL_GEOMETRY_VERTICES_OUT_EXT,vertexOut);
|
|
//glProgramParameteriEXT(_program,GL_GEOMETRY_OUTPUT_TYPE_EXT,outputType);
|
|
glAttachShader(_program, fragmentShader);
|
|
glLinkProgram(_program);
|
|
|
|
{$ifdef NV_REPORT_COMPILE_ERRORS}
|
|
//Get error log.
|
|
glGetProgramiv(_program, GL_INFO_LOG_LENGTH, @infoLogLength);
|
|
|
|
infoLog := StringOfChar(' ',infoLogLength);
|
|
glGetProgramInfoLog(_program, infoLogLength, @charsWritten, @infoLog[1]);
|
|
writeln(stdout, infoLog);
|
|
{$endif}
|
|
|
|
//Test linker result.
|
|
linkSucceed := GL_FALSE;
|
|
glGetProgramiv(_program, GL_LINK_STATUS, @linkSucceed);
|
|
if linkSucceed = GL_FALSE then
|
|
begin
|
|
glDeleteProgram(_program);
|
|
Result := 0;
|
|
exit;
|
|
end;
|
|
|
|
Result := _program;
|
|
end;
|
|
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
function CompileASMShader(program_type: GLenum; code: string): GLuint;
|
|
var
|
|
{$ifdef NV_REPORT_COMPILE_ERRORS}
|
|
error_string: string;
|
|
{$endif}
|
|
program_id: GLuint;
|
|
error_pos: GLint;
|
|
begin
|
|
glGenProgramsARB(1, @program_id);
|
|
glBindProgramARB(program_type, program_id);
|
|
glProgramStringARB(program_type, GL_PROGRAM_FORMAT_ASCII_ARB, length(code), @code[1]);
|
|
|
|
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, @error_pos);
|
|
if error_pos <> -1 then
|
|
begin
|
|
{$ifdef NV_REPORT_COMPILE_ERRORS}
|
|
error_string := glGetString(GL_PROGRAM_ERROR_STRING_ARB);
|
|
writeln(stderr, 'Program error at position: ', error_pos);
|
|
writeln(stderr, error_string);
|
|
{$endif}
|
|
Result := 0;
|
|
exit;
|
|
end;
|
|
|
|
Result := program_id;
|
|
end;
|
|
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
function CompileASMShaderFromFile(target: GLenum; filename: string): GLuint;
|
|
var
|
|
program_id: GLuint;
|
|
s: TStrings;
|
|
begin
|
|
//must read files as binary to prevent problems from newline translation
|
|
try
|
|
try
|
|
s := TStringList.Create;
|
|
s.LoadFromFile(filename);
|
|
|
|
program_id := CompileASMShader(target, s.Text);
|
|
Result := program_id;
|
|
exit;
|
|
finally
|
|
FreeAndNil(s);
|
|
end;
|
|
except
|
|
Result := 0;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|