Если вам нужно выполнить преобразование HSL на текстуре OpenGL в Delphi, вам понадобится использовать шейдеры. Шейдеры - это небольшие программы, которые выполняются на графическом процессоре и используются для изменения цвета, текстуры и других атрибутов объектов в реальном времени.
В этой статье мы покажем вам, как создать функцию в Delphi, которая принимает текстуру и три значения - сдвиг оттенка в градусах и множители насыщенности и яркости от 0 до 2, и применяет эти преобразования к текстуре перед ее отображением.
Шаг 1: Создание шейдера
Первый шаг - создать шейдер, который будет выполнять преобразование HSL. Для этого нам понадобится использовать язык программирования, такой как GLSL (OpenGL Shading Language). Вот пример шейдера, который принимает текстуру, сдвиг оттенка, множители насыщенности и яркости и возвращает преобразованную текстуру:
#version 330 core
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D inputTexture;
uniform float hShift;
uniform float sMult;
uniform float lMult;
void main(){
vec4 color = texture(inputTexture, TexCoord);
// Convert RGB to HSL
float h = (color.r + color.g + color.b) / 3.0;
float s = (max(color.r, max(color.g, color.b)) - min(color.r, min(color.g, color.b))) / (max(color.r, max(color.g, color.b)) + min(color.r, min(color.g, color.b)));
float l = (color.r + color.g + color.b) / 3.0;
// Apply HSL shift and multipliers
h = (h + hShift) % 360.0;
s = s * sMult;
l = l * lMult;
// Convert HSL back to RGB
float r, g, b;
if(s == 0.0){
r = g = b = l; // achromatic
}else{
float temp1 = (l + s) / 2.0;
float temp2 = (2.0 * l - temp1) * abs(h / 360.0 - 1.0);
float temp3 = temp1 - abs((h / 360.0) - 1.0) * temp2;
if(h < 120.0){
r = temp2;
g = temp3;
b = (l - s);
}else if(h < 240.0){
r = (l - s);
g = temp2;
b = temp3;
}else{
r = temp3;
g = (l - s);
b = temp2;
}
}
FragColor = vec4(r, g, b, color.a);
}
Шаг 2: Компиляция шейдера
После написания шейдера, нам нужно его скомпилировать и связать с программой. Для этого мы будем использовать OpenGL. Вот как это можно сделать в Delphi:
procedure CompileShader(const shaderSource: string; shaderType: GLenum; var shaderID: GLuint);
var
status: GLint;
begin
shaderID := glCreateShader(shaderType);
with shaderID do
begin
glShaderSource(shaderID, 1, [shaderSource], nil);
glCompileShader(shaderID);
glGetShaderiv(shaderID, GL_COMPILE_STATUS, @status);
if (status = GL_FALSE) then
raise Exception.Create('Shader compilation failed');
end;
end;
Эта процедура принимает исходный код шейдера, тип шейдера (GL_VERTEX_SHADER или GL_FRAGMENT_SHADER) и возвращает идентификатор скомпилированного шейдера.
Шаг 3: Связывание шейдера
После того, как мы скомпилировали шейдер, нам нужно его связать с программой. Для этого мы создадим пустую программу и добавим в нее наш шейдер:
procedure LinkShader(const vertexShaderID, fragmentShaderID: GLuint; var programID: GLuint);
var
status: GLint;
begin
programID := glCreateProgram();
with programID do
begin
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
glGetProgramiv(programID, GL_LINK_STATUS, @status);
if (status = GL_FALSE) then
raise Exception.Create('Program linking failed');
end;
end;
Эта процедура принимает идентификаторы скомпилированных вершинного и фрагментного шейдеров и возвращает идентификатор связанной программы.
Шаг 4: Применение шейдера
Теперь, когда у нас есть связанная программа, мы можем применить шейдер к нашей текстуре. Для этого мы создадим функцию, которая принимает текстуру, сдвиг оттенка, множители насыщенности и яркости и применяет шейдер к текстуре:
procedure HSLTransform(texture: GLuint; hShift: GLfloat; sMult, lMult: GLfloat);
var
programID: GLuint;
uniformLocation: GLint;
begin
// Compile and link shaders
CompileShader('...', GL_FRAGMENT_SHADER, fragmentShaderID);
CompileShader('...', GL_VERTEX_SHADER, vertexShaderID);
LinkShader(vertexShaderID, fragmentShaderID, programID);
// Bind the program
glUseProgram(programID);
// Set the values of the uniform parameters
uniformLocation := glGetUniformLocation(programID, 'inputTexture');
glUniform1i(uniformLocation, 0);
uniformLocation := glGetUniformLocation(programID, 'hShift');
glUniform1f(uniformLocation, hShift);
uniformLocation := glGetUniformLocation(programID, 'sMult');
glUniform1f(uniformLocation, sMult);
uniformLocation := glGetUniformLocation(programID, 'lMult');
glUniform1f(uniformLocation, lMult);
// Bind the source texture to read from
glBindTexture(GL_TEXTURE_2D, texture);
// Render a quad
glBegin(GL_QUADS);
glVertex2i(0, 0);
glVertex2i(1, 0);
glVertex2i(1, 1);
glVertex2i(0, 1);
glEnd();
end;
Эта функция принимает идентификатор текстуры, сдвиг оттенка, множители насыщенности и яркости и применяет шейдер к текстуре перед ее отображением.
Использование альтернативного подхода
Если вам не нужно выполнять преобразование HSL в реальном времени, вы можете использовать альтернативный подход, который заключается в получении пикселей текстуры и изменении их в коде Delphi. Вот пример кода, который демонстрирует этот подход:
procedure ModifyTexturePixels(texture: GLuint);
var
pixels: PByte;
width, height: GLint;
begin
// Get texture dimensions
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL\_TEXTURE\_WIDTH, @width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL\_TEXTURE\_HEIGHT, @height);
// Get copy of pixels
GetMem(pixels, width * height * 4);
glGetTexImage(GL\_TEXTURE\_2D, 0, GL\_RGBA, GL\_UNSIGNED\_BYTE, pixels);
// Modify pixels here
...
// Update texture with modified pixels
glTexImage2D(GL\_TEXTURE\_2D, 0, GL\_RGBA, width, height, 0, GL\_RGBA, GL\_UNSIGNED\_BYTE, pixels);
FreeMem(pixels);
end;
Преобразование HSL на текстуре OpenGL в Delphi выполняется с помощью шейдеров, которые применяют сдвиг оттенка, множители насыщенности и яркости к текстуре перед ее отображением.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.