Форум программистов, компьютерный форум, киберфорум
OpenGL
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.50/18: Рейтинг темы: голосов - 18, средняя оценка - 4.50
175 / 10 / 1
Регистрация: 05.08.2024
Сообщений: 73

Как сделать перемещение камеры в PyOpenGL?

28.08.2024, 20:55. Показов 6658. Ответов 65
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Мне помог один человек (в целях конфиденциальности я решил не писать его username) с изучением OpenGL с помощью Python. Я взял его код с крутящимся синим кубиком (фигур было больше, но для удобства я решил оставить одну). Код изучил я подробно, но возникла проблема с перемещением камеры клавишами: я не знаю как их сделать. Помогите, пожалуйста.
Вот код:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import ctypes
import math
 
import numpy as np
import pygame
from OpenGL.GL import *
from OpenGL.GL.shaders import *
from pygame.locals import *
from pyrr import *
 
vertexShaderSource = """
    attribute vec3 aPosition;
    uniform mat4 uMvpMatrix;
 
    void main()
    {
        gl_Position = uMvpMatrix * vec4(aPosition, 1.0);
    }
"""
 
fragmentShaderSource = """
    uniform vec3 uColor;
 
    void main()
    {
        gl_FragColor = vec4(uColor, 1.0);
    }
"""
 
def main():
    pygame.init()
    winWidth, winHeight = 800, 600
    display = (winWidth, winHeight)
 
    pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
    
    #передаем глубину
    glEnable(GL_DEPTH_TEST)
 
    program = compileProgram(
       compileShader(vertexShaderSource, GL_VERTEX_SHADER),
       compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER))
    glUseProgram(program)
 
    # Create a cube
    #    v6----- v5
    #   /|      /|
    #  v1------v0|
    #  | |     | |
    #  | |v7---|-|v4
    #  |/      |/
    #  v2------v3
    vertPositions = np.array([
        -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, # v2-v3-v1-v0 front
        0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, # v3-v4-v0-v5 right
        -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, # v1-v0-v6-v5 up
        -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, # v7-v2-v6-v1 left
        -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, # v7-v4-v2-v3 down
        0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5 # v4-v7-v5-v6 back
    ], dtype=np.float32)
    vertPosBuffer = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer)
    glBufferData(GL_ARRAY_BUFFER, len(vertPositions) * 4,
        vertPositions, GL_STATIC_DRAW)
 
    #работа с шейдерами    (достаем позицию фигуры)
    aPositionLocation = glGetAttribLocation(program, "aPosition")
    glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
    glEnableVertexAttribArray(aPositionLocation)
 
    uColorLocation = glGetUniformLocation(program, "uColor")
    uMvpMatrixLocation = glGetUniformLocation(program, "uMvpMatrix")
 
    #перспектива
    projMatrix = matrix44.create_perspective_projection(fovy=45, aspect=winWidth/winHeight,
        near=0.1, far=1000)
    
    #положение камеры
    viewMatrix = matrix44.create_look_at(
        #позиция камеры
        eye=vector3.create(0, 20, 50),
        #место, в которое смотрит камера
        target=vector3.create(0, 0, 0),
        #направление вверх
        up=vector3.create(0, 1, 0))
    
    #объединяем положение камеры и перспективу
    projViewMatrix = matrix44.multiply(viewMatrix, projMatrix)
 
    #новая позиция фигуры
    position1 = vector3.create(0, 5, 0)
    
    #угол
    angle1 = 0
    
    #размер                 x    y   z
    scale1 = vector3.create(10, 10, 10)
    
    #цвет
    color1 = vector3.create(0.5, 0.5, 1)
 
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
 
        # передаем новою позицию куба
        translationMatrix = matrix44.create_from_translation(position1)
        
        #по какому углу будем изменять положение фигуры:
        #                                     x  (от этой буквы зависит перемещение фигуры по x, y, z)
        #                                    \/
        rotationMatrix = matrix44.create_from_x_rotation(math.radians(angle1))
        
        #передаем значения размера куба
        scaleMatrix = matrix44.create_from_scale(scale1)
        
        #передаем начальные координаты и координаты перемещения куба
        modelMatrix = matrix44.multiply(rotationMatrix, translationMatrix)
        
        #передаем координаты и размеры куба, объединяя их в одно целое
        modelMatrix = matrix44.multiply(scaleMatrix, modelMatrix)
        
        #объединяем матрицы вида, а также фигуру
        mvpMatrix = matrix44.multiply(modelMatrix, projViewMatrix)
        
        
        glUniformMatrix4fv(uMvpMatrixLocation, 1, GL_FALSE, mvpMatrix)
        
        #передаем цвет фигуры
        glUniform3fv(uColorLocation, 1, color1)
        
        #отрисовываем фигуру
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 24)
        
        #во время цикла изменяем градус угла поворота куба
        angle1 += 1
 
        pygame.display.flip()
        pygame.time.wait(10)
 
main()
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
28.08.2024, 20:55
Ответы с готовыми решениями:

Как сделать плавное перемещение камеры вниз или вверх?
Здравствуйте!начну с того что я тупой и не могу самостоятельно написать скрипт на c#. Помогите пожалуйста, что мне нужно дополнить в...

Как сделать перемещение камеры в пространстве по типу FPS шутера
Как сделать перемещение камеры в пространстве по типу FPS шутера? Без тормозов. Даже без вращения, просто анимировать перемещение камеры к...

Как сделать изменение координат (или анимацию) в PyOpenGL?
Код создает несколько треугольников и один синий квадрат. Как сделать так, чтобы синий квадрат мог вращаться, не изменяя своих пропорций, а...

65
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
08.09.2024, 18:13
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Daniil_G Посмотреть сообщение
Возможно ли скрещивание FBO и класса отрисовки, чтобы это могло работать исправно
Пример из прошлой темы с FBO использует библиотеку Pyrr для работы с матрицами и векторами. Я заменил Pyrr на PyGLM, потому что она мне кажется более удобной и более универсальной, так как можно будет не переучиваться при программировании на C++. Пример загрузил на Gist. Сделаем так. Вы скрещиваете мой пример с классом model.py, который прикреплён архивом к сообщению #39 и ваш пример с моими правками из сообщения #32, то есть вы для каждого объекта создаёте экземпляр класса Model, передавая в конструктор этого класса массив вершин и массив нормалей. После этого я беру ваш код и добавляю в него тени. Вам надо под объектами расположить большую плоскость или сплюснутый куб, чтобы я мог отобразить тени.



main.py

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# pip install Pygame PyOpenGL PyGLM numpy
# python main.py
 
import ctypes
import math
 
import glm
import numpy as np
import pygame
from OpenGL.GL import *
from OpenGL.GL.shaders import *
from pygame.locals import *
 
from fbo import initFBO
 
vertexShaderSource = """
    attribute vec4 aPosition;
    attribute vec4 aNormal;
 
    uniform mat4 uNormalMatrix;
    uniform mat4 uMvpMatrix;
    uniform mat4 uMvpMatrixFromLight;
 
    const vec3 lightPosition = vec3(-10.0, 50.0, 30.0);
    const vec3 lightDirection = normalize(lightPosition);
    const float ambient = 0.3;
 
    varying float vDot;
    varying vec4 vPositionFromLight;
 
    void main()
    {
        gl_Position = uMvpMatrix * aPosition;
        vPositionFromLight = uMvpMatrixFromLight * aPosition;
        vec4 normal = uNormalMatrix * aNormal;
        vDot = max(dot(normalize(normal.xyz), lightDirection), ambient);
    }
"""
 
fragmentShaderSource = """
    uniform vec3 uColor;
    uniform sampler2D uShadowMap;
    uniform bool uReceiveShadow;
 
    const vec3 lightColor = vec3(1.0, 1.0, 1.0);
 
    varying float vDot;
    varying vec4 vPositionFromLight;
 
    void main()
    {
        vec3 diffuse = lightColor * uColor * vDot;
 
        if (uReceiveShadow)
        {
            vec3 shadowCoord = (vPositionFromLight.xyz/vPositionFromLight.w)/2.0 + 0.5;
            vec4 rgbaDepth = texture2D(uShadowMap, shadowCoord.xy);
            float depth = rgbaDepth.r; // Retrieve the z-value from R
            float visibility = (shadowCoord.z > depth + 0.005) ? 0.7 : 1.0;
            gl_FragColor = vec4(diffuse * visibility, 1.0);
        }
        else
        {
            gl_FragColor = vec4(diffuse, 1.0);
        }
    }
"""
 
shadowMapVertexShaderSource = """
    attribute vec4 aPosition;
    uniform mat4 uMvpMatrix;
 
    void main()
    {
        gl_Position = uMvpMatrix * aPosition;
    }
"""
 
shadowMapFragmentShaderSource = """
    void main()
    {
        // Write the z-value in R
        gl_FragColor = vec4(gl_FragCoord.z, 0.0, 0.0, 0.0);
    }
"""
 
def main():
    pygame.init()
    winWidth, winHeight = 400, 300
    display = (winWidth, winHeight)
 
    pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
    
    glEnable(GL_DEPTH_TEST)
    glClearColor(0.2, 0.2, 0.2, 1)
 
    program = compileProgram(
       compileShader(vertexShaderSource, GL_VERTEX_SHADER),
       compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER))
    glUseProgram(program)
 
    # Create a cube
    #    v6----- v5
    #   /|      /|
    #  v1------v0|
    #  | |     | |
    #  | |v7---|-|v4
    #  |/      |/
    #  v2------v3
    vertPositions = np.array([
        -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, # v2-v3-v1 front
        -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, # v1-v3-v0 front
        0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, # v3-v4-v0 right
        0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, # v0-v4-v5 right
        -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, # v1-v0-v6 up
        -0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, # v6-v0-v5 up
        -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, # v7-v2-v6 left
        -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, # v6-v2-v1 left
        -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, # v7-v4-v2 down
        -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, # v2-v4-v3 down
        0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, # v4-v7-v5 back
        0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5 # v5-v7-v6 back
    ], dtype=np.float32)
    vertPosBuffer = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer)
    glBufferData(GL_ARRAY_BUFFER, len(vertPositions) * 4,
        vertPositions, GL_STATIC_DRAW)
 
    normals = np.array([
        0, 0, 1, 0, 0, 1, 0, 0, 1, # v2-v3-v1 front
        0, 0, 1, 0, 0, 1, 0, 0, 1, # v1-v3-v0 front
        1, 0, 0, 1, 0, 0, 1, 0, 0, # v3-v4-v0 right
        1, 0, 0, 1, 0, 0, 1, 0, 0, # v0-v4-v5 right
        0, 1, 0, 0, 1, 0, 0, 1, 0, # v1-v0-v6 up
        0, 1, 0, 0, 1, 0, 0, 1, 0, # v6-v0-v5 up
        -1, 0, 0, -1, 0, 0, -1, 0, 0, # v7-v2-v6 left
        -1, 0, 0, -1, 0, 0, -1, 0, 0, # v6-v2-v1 left
        0, -1, 0, 0, -1, 0, 0, -1, 0, # v7-v4-v2 down
        0, -1, 0, 0, -1, 0, 0, -1, 0, # v2-v4-v3 down
        0, 0, -1, 0, 0, -1, 0, 0, -1, # v4-v7-v5 back
        0, 0, -1, 0, 0, -1, 0, 0, -1 # v5-v7-v6 back
    ], dtype=np.float32)
    normalBuffer = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, normalBuffer)
    glBufferData(GL_ARRAY_BUFFER, len(normals) * 4,
        normals, GL_STATIC_DRAW)
 
    aPositionLocation = glGetAttribLocation(program, "aPosition")
    aNormalLocation = glGetAttribLocation(program, "aNormal")
    uColorLocation = glGetUniformLocation(program, "uColor")
    uReceiveShadowLocation = glGetUniformLocation(program, "uReceiveShadow")
    uNormalMatrixLocation = glGetUniformLocation(program, "uNormalMatrix")
    uMvpMatrixLocation = glGetUniformLocation(program, "uMvpMatrix")
    uShadowMapLocation = glGetUniformLocation(program, "uShadowMap")
    glUniform1i(uShadowMapLocation, 0)
    uMvpMatrixFromLightLocation = glGetUniformLocation(program, "uMvpMatrixFromLight")
 
    shadowMapProgram = compileProgram(
       compileShader(shadowMapVertexShaderSource, GL_VERTEX_SHADER),
       compileShader(shadowMapFragmentShaderSource, GL_FRAGMENT_SHADER))
    glUseProgram(shadowMapProgram)
    aPositionLocationForShadow = glGetAttribLocation(shadowMapProgram, "aPosition")
    uMvpMatrixLocationForShadow = glGetUniformLocation(shadowMapProgram, "uMvpMatrix")
 
    projMatrix = glm.perspective(math.radians(45), winWidth/winHeight, 0.1, 1000)
    viewMatrix = glm.lookAt(
        glm.vec3(0, 20, 60), # position
        glm.vec3(0, 0, 0), # target
        glm.vec3(0, 1, 0)) # up
    projViewMatrix = projMatrix * viewMatrix
 
    offscreenWidth, offscreenHeight = 2048, 2048
    shadowMapTexture, framebuffer = initFBO(offscreenWidth, offscreenHeight)
 
    projMatrixFromLight = glm.ortho(-200, 200, -200, 200, -50, 200)
    viewMatrixFromLight = glm.lookAt(
        glm.vec3(-10, 50, 30), # position
        glm.vec3(0, 0, 0), # target
        glm.vec3(0, 1, 0)) # up
    projViewMatrixFromLight = projMatrixFromLight * viewMatrixFromLight
 
    position1 = glm.vec3(7, 5, 0)
    angle1 = 0
    scale1 = glm.vec3(10, 10, 10)
    color1 = glm.vec3(0.5, 0.5, 1)
 
    position2 = glm.vec3(-7, 5, 0)
    angle2 = 0
    scale2 = glm.vec3(8, 10, 10)
    color2 = glm.vec3(1, 0.5, 0.5)
 
    groundPosition = glm.vec3(0, -10, 0)
    groundScale = glm.vec3(40, 3, 40)
    groundColor = glm.vec3(0.5, 1, 0.5)
 
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
 
        # Change the drawing destination to FBO
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer)
        glViewport(0, 0, offscreenWidth, offscreenHeight)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glUseProgram(shadowMapProgram)
 
        # Cuboids
        glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer)
        glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
        glEnableVertexAttribArray(aPositionLocation)
 
        # Cube
        # Model matrix
        modelMatrix = glm.translate(glm.mat4(1), position1)
        modelMatrix = glm.rotate(modelMatrix, math.radians(angle1), glm.vec3(1, 0, 0))
        modelMatrix = glm.scale(modelMatrix, scale1)
        # MVP-matrix
        mvpMatrixFromLightForCube = projViewMatrixFromLight * modelMatrix
        glUniformMatrix4fv(uMvpMatrixLocationForShadow, 1, GL_FALSE,
            glm.value_ptr(mvpMatrixFromLightForCube))
        glDrawArrays(GL_TRIANGLES, 0, 36)
 
        # Cuboid
        # Model matrix
        modelMatrix = glm.translate(glm.mat4(1), position2)
        modelMatrix = glm.rotate(modelMatrix, math.radians(angle2), glm.vec3(0, 0, 1))
        modelMatrix = glm.scale(modelMatrix, scale2)
        # MVP-matrix
        mvpMatrixFromLightForCuboid = projViewMatrixFromLight * modelMatrix
        glUniformMatrix4fv(uMvpMatrixLocationForShadow, 1, GL_FALSE,
            glm.value_ptr(mvpMatrixFromLightForCuboid))
        glDrawArrays(GL_TRIANGLES, 0, 36)
 
        # Ground
        # Model matrix
        modelMatrix = glm.translate(glm.mat4(1), groundPosition)
        modelMatrix = glm.scale(modelMatrix, groundScale)
        # MVP-matrix
        mvpMatrixFromLightForGround = projViewMatrixFromLight * modelMatrix
        glUniformMatrix4fv(uMvpMatrixLocationForShadow, 1, GL_FALSE,
            glm.value_ptr(mvpMatrixFromLightForGround))
        glDrawArrays(GL_TRIANGLES, 0, 36)
 
        glBindFramebuffer(GL_FRAMEBUFFER, 0)
 
        glUseProgram(program)
        glViewport(0, 0, winWidth, winHeight)
 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
 
        glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer)
        glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
        glEnableVertexAttribArray(aPositionLocation)
 
        glBindBuffer(GL_ARRAY_BUFFER, normalBuffer)
        glVertexAttribPointer(aNormalLocation, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
        glEnableVertexAttribArray(aNormalLocation)
 
        # Cube
        # Model matrix
        modelMatrix = glm.translate(glm.mat4(1), position1)
        modelMatrix = glm.rotate(modelMatrix, math.radians(angle1), glm.vec3(1, 0, 0))
        modelMatrix = glm.scale(modelMatrix, scale1)
        # Normal matrix
        normalMatrix = glm.inverse(modelMatrix)
        normalMatrix = glm.transpose(normalMatrix)
        glUniformMatrix4fv(uNormalMatrixLocation, 1, GL_FALSE, glm.value_ptr(normalMatrix))
        # MVP-matrix
        mvpMatrix = projViewMatrix * modelMatrix
        glUniformMatrix4fv(uMvpMatrixLocation, 1, GL_FALSE, glm.value_ptr(mvpMatrix))
        # Color
        glUniform3fv(uColorLocation, 1, glm.value_ptr(color1))
        glUniform1i(uReceiveShadowLocation, 0)
        glDrawArrays(GL_TRIANGLES, 0, 36)
        angle1 += 1
 
        # Cuboid
        # Model matrix
        modelMatrix = glm.translate(glm.mat4(1), position2)
        modelMatrix = glm.rotate(modelMatrix, math.radians(angle2), glm.vec3(0, 0, 1))
        modelMatrix = glm.scale(modelMatrix, scale2)
        # Normal matrix
        normalMatrix = glm.inverse(modelMatrix)
        normalMatrix = glm.transpose(normalMatrix)
        glUniformMatrix4fv(uNormalMatrixLocation, 1, GL_FALSE, glm.value_ptr(normalMatrix))
        # MVP-matrix
        mvpMatrix = projViewMatrix * modelMatrix
        glUniformMatrix4fv(uMvpMatrixLocation, 1, GL_FALSE, glm.value_ptr(mvpMatrix))
        # Color
        glUniform3fv(uColorLocation, 1, glm.value_ptr(color2))
        glUniform1i(uReceiveShadowLocation, 0)
        glDrawArrays(GL_TRIANGLES, 0, 36)
        angle2 -= 3
 
        # Ground
        glBindTexture(GL_TEXTURE_2D, shadowMapTexture)
        # Model matrix
        modelMatrix = glm.translate(glm.mat4(1), groundPosition)
        modelMatrix = glm.scale(modelMatrix, groundScale)
        # Normal matrix
        normalMatrix = glm.inverse(modelMatrix)
        normalMatrix = glm.transpose(normalMatrix)
        glUniformMatrix4fv(uNormalMatrixLocation, 1, GL_FALSE, glm.value_ptr(normalMatrix))
        # MVP-matrix
        mvpMatrix = projViewMatrix * modelMatrix
        glUniformMatrix4fv(uMvpMatrixLocation, 1, GL_FALSE, glm.value_ptr(mvpMatrix))
        glUniformMatrix4fv(uMvpMatrixFromLightLocation, 1, GL_FALSE,
            glm.value_ptr(mvpMatrixFromLightForGround))
        # Color
        glUniform3fv(uColorLocation, 1, glm.value_ptr(groundColor))
        glUniform1i(uReceiveShadowLocation, 1)
        glDrawArrays(GL_TRIANGLES, 0, 36)
 
        pygame.display.flip()
        pygame.time.wait(10)
 
main()
fbo.py

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from OpenGL.GL import *
 
 
def initFBO(offscreenWidth, offscreenHeight):
    # Create a texture object and set its size and parameters
    shadowMapTexture = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, shadowMapTexture)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, offscreenWidth, offscreenHeight,
        0, GL_RGBA, GL_UNSIGNED_BYTE, None)
 
    # Create a renderbuffer object and Set its size and parameters
    depthBuffer = glGenRenderbuffers(1)
    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer)
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
        offscreenWidth, offscreenHeight)
 
    # Attach the texture and the renderbuffer object to the FBO
    # Create a frame buffer object (FBO)
    framebuffer = glGenFramebuffers(1)
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer)
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
        GL_TEXTURE_2D, shadowMapTexture, 0)
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
        GL_RENDERBUFFER, depthBuffer)
    e = glCheckFramebufferStatus(GL_FRAMEBUFFER)
    if e != GL_FRAMEBUFFER_COMPLETE:
        print("Frame buffer object is incomplete")
 
    glBindFramebuffer(GL_FRAMEBUFFER, 0)
    glBindTexture(GL_TEXTURE_2D, 0)
    glBindRenderbuffer(GL_RENDERBUFFER, 0)
 
    return (shadowMapTexture, framebuffer)
Миниатюры
1
175 / 10 / 1
Регистрация: 05.08.2024
Сообщений: 73
08.09.2024, 20:33  [ТС]
Хорошо

Добавлено через 2 часа 10 минут
Здравствуйте! Я попытался сделать на ночь глядя код, чтобы он доставал нужные объекты для теней, но их не использовал. Вдруг у меня возникла проблема с классами, а с ними я не очень хорош (а точнее импортом функций из класса).
Вот код, который у меня получился на нынешний момент:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
import ctypes
import math
 
import glm
import numpy as np
import pygame
from OpenGL.GL import *
from OpenGL.GL.shaders import *
from pygame.locals import *
#from pyrr import *
 
#
def FBO(offscreenWidth, offscreenHeight):
    # 
    shadowMapTexture = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, shadowMapTexture)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, offscreenWidth, offscreenHeight,
        0, GL_RGBA, GL_UNSIGNED_BYTE, None)
 
    #
    depthBuffer = glGenRenderbuffers(1)
    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer)
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
        offscreenWidth, offscreenHeight)
 
    # 
    framebuffer = glGenFramebuffers(1)
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer)
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
        GL_TEXTURE_2D, shadowMapTexture, 0)
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
        GL_RENDERBUFFER, depthBuffer)
    
    #
    glBindFramebuffer(GL_FRAMEBUFFER, 0)
    glBindTexture(GL_TEXTURE_2D, 0)
    glBindRenderbuffer(GL_RENDERBUFFER, 0)
 
    return (shadowMapTexture, framebuffer)
 
#        
 
#
vertexShaderSource = """
    attribute vec4 aPosition;
    attribute vec4 aNormal;
 
    uniform mat4 uNormalMatrix;
    uniform mat4 uMvpMatrix;
    uniform mat4 uMvpMatrixFromLight;
 
    const vec3 lightPosition = vec3(-10.0, 50.0, 30.0);
    const vec3 lightDirection = normalize(lightPosition);
    const float ambient = 0.3;
 
    varying float vDot;
    varying vec4 vPositionFromLight;
 
    void main()
    {
        gl_Position = uMvpMatrix * aPosition;
        vPositionFromLight = uMvpMatrixFromLight * aPosition;
        vec4 normal = uNormalMatrix * aNormal;
        vDot = max(dot(normalize(normal.xyz), lightDirection), ambient);
    }
"""
 
 
fragmentShaderSource = """
    uniform vec3 uColor;
    uniform sampler2D uShadowMap;
    uniform bool uReceiveShadow;
 
    const vec3 lightColor = vec3(1.0, 1.0, 1.0);
 
    varying float vDot;
    varying vec4 vPositionFromLight;
 
    void main()
    {
        vec3 diffuse = lightColor * uColor * vDot;
 
        if (uReceiveShadow)
        {
            vec3 shadowCoord = (vPositionFromLight.xyz/vPositionFromLight.w)/2.0 + 0.5;
            vec4 rgbaDepth = texture2D(uShadowMap, shadowCoord.xy);
            float depth = rgbaDepth.r; // Retrieve the z-value from R
            float visibility = (shadowCoord.z > depth + 0.005) ? 0.7 : 1.0;
            gl_FragColor = vec4(diffuse * visibility, 1.0);
        }
        else
        {
            gl_FragColor = vec4(diffuse, 1.0);
        }
    }
"""
 
#
shadowMapVertexShaderSource = """
    attribute vec4 aPosition;
    uniform mat4 uMvpMatrix;
 
    void main()
    {
        gl_Position = uMvpMatrix * aPosition;
    }
"""
 
#
shadowMapFragmentShaderSource = """
    void main()
    {
        // Write the z-value in R
        gl_FragColor = vec4(gl_FragCoord.z, 0.0, 0.0, 0.0);
    }
"""
 
#
class Model:
 
    def __init__(self, vertPositions, program, position, angle, scale, color):
        # Сохраняем входные переменные
        self.program = program
        self.position = position
        self.angle = angle
        self.scale = scale
        self.color = color
 
        #
        self.amountOfVertices = len(vertPositions) // 2
 
        #
        vertPositions = np.array(vertPositions, dtype=np.float32)
 
        #
        self.vertPosBuffer = glGenBuffers(1)
        #
        glBindBuffer(GL_ARRAY_BUFFER, self.vertPosBuffer)
        #
        glBufferData(GL_ARRAY_BUFFER, len(vertPositions) * 4,
            vertPositions, GL_STATIC_DRAW)
 
        #
        self.aPositionLocation = glGetAttribLocation(self.program, "aPosition")
        #
        self.aNormalLocation = glGetAttribLocation(self.program, "aNormal")
        #
        self.uColorLocation = glGetUniformLocation(self.program, "uColor")
        #
        self.uReceiveShadowLocation = glGetUniformLocation(self.program, "uReceiveShadow")
        #
        self.uNormalMatrixLocation = glGetUniformLocation(self.program, "uNormalMatrix")
        #
        self.uMvpMatrixLocation = glGetUniformLocation(self.program, "uMvpMatrix")
        #
        self.uShadowMapLocation = glGetUniformLocation(self.program, "uShadowMap")
        glUniform1i(self.uShadowMapLocation, 0)
        #
        self.uMvpMatrixFromLightLocation = glGetUniformLocation(self.program, "uMvpMatrixFromLight")        
 
    def draw(self, projViewMatrix):
        glUseProgram(self.program)
        #
        glBindBuffer(GL_ARRAY_BUFFER, self.vertPosBuffer)
 
        #
        glEnableVertexAttribArray(self.aPositionLocation)
        glVertexAttribPointer(self.aPositionLocation, 2, GL_FLOAT, GL_FALSE,
            0, ctypes.c_void_p(0))
 
        #
        modelMatrix = glm.translate(glm.mat4(1), self.position)
        # Rotate
        modelMatrix = glm.rotate(modelMatrix, glm.radians(self.angle),
            glm.vec3(0, 0, 1))
        # Scale
        modelMatrix = glm.scale(modelMatrix, self.scale)
        mvpMatrix = projViewMatrix * modelMatrix
        glUniformMatrix4fv(self.uMvpMatrixLocation, 1, GL_FALSE,
            glm.value_ptr(mvpMatrix))
 
        # Send a color to the fragment shader
        glUniform3fv(self.uColorLocation, 1, glm.value_ptr(self.color))
 
        # Draw the model
        glDrawArrays(GL_TRIANGLES, 0, self.amountOfVertices)
 
def main():
    pygame.init()
    winWidth, winHeight = 900, 600
    display = (winWidth, winHeight)
         
    pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
         
    # Set a background color
    glClearColor(0.7, 0.7, 0.7, 1)
        
    # Triangle vertex positions
    triangleVertPositions = [
        -0.5, -0.5, 0.5,
        0.5, -0.5, 0.5,
        0, 0.5, 0.5
         ]
    #
    program = compileProgram(
        compileShader(vertexShaderSource, GL_VERTEX_SHADER),
        compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER))
    #glUseProgram(program)
    #
    shadowMapProgram = compileProgram(
        compileShader(shadowMapVertexShaderSource, GL_VERTEX_SHADER),
        compileShader(shadowMapFragmentShaderSource, GL_FRAGMENT_SHADER))
    #glUseProgram(shadowMapProgram) 
    
    # Create models
    triangle = Model(
        vertPositions = triangleVertPositions,
        program = program,
        position = glm.vec3(50, 50, 0),
        angle = 20,
        scale = glm.vec3(50, 50, 1),
        color = glm.vec3(0.74, 0.58, 0.15))
    
    #
    projMatrix = glm.perspective(math.radians(45), winWidth/winHeight, 0.1, 1000)
    #
    viewMatrix = glm.lookAt(
        glm.vec3(0, 20, 60), # 
        glm.vec3(0, 0, 0), #
        glm.vec3(0, 1, 0)) #
    #
    projViewMatrix = projMatrix * viewMatrix
    
    # Main loop
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
 
        # Clear the canvas
        glClear(GL_COLOR_BUFFER_BIT)
  
        # Draw models
        triangle.draw(projViewMatrix)
 
        # Flip the back the front screen buffer
        pygame.display.flip()
        # Wait 10 msec
        pygame.time.wait(10)
 
if __name__ == "__main__":
    main()
0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
08.09.2024, 21:44
Цитата Сообщение от Daniil_G Посмотреть сообщение
а точнее импортом функций из класса
Пример, с классом Model в файле model.py показывает, как импортировать класс из файла, как создавать экземпляр класса и как вызывать метод. Если вы не знаете, как работать с классами, то вот простейший пример. Вынесите теперь Model в отдельный класса, а функцию FBO пока удалите.

main.py

Python
1
2
3
4
from my_class import MyClass
 
obj = MyClass()
obj.myMethod()
my_class.py

Python
1
2
3
4
class MyClass:
 
    def myMethod(self):
        print("My method was called")
0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
09.09.2024, 10:44
Цитата Сообщение от Daniil_G Посмотреть сообщение
Я попытался сделать на ночь глядя код, чтобы он доставал нужные объекты для теней, но их не использовал.
Ваш код выдаёт ошибку на строке 159:

Code
1
2
  File "main.py", line 159, in __init__
    glUniform1i(self.uShadowMapLocation, 0)
"ShadowMap" - это для теней. Вы не поняли меня. Не надо пока добавлять тени. Вы скачиваете архив прикреплённый к сообщению #39, где создаётся класс Model и добавляете в него загрузку моделей из файлов, как в примере из сообщения #32, передавая в конструктор класса Model кроме vertPositions ещё и normals, вот так:

Python
1
2
3
4
5
6
7
8
import glm
import numpy as np
from OpenGL.GL import *
 
 
class Model:
 
    def __init__(self, vertPositions, normals, program, position, angle, scale, color):
1
175 / 10 / 1
Регистрация: 05.08.2024
Сообщений: 73
11.09.2024, 17:15  [ТС]
Здравствуйте! Я попытался сделать код, но у меня как всегда, появилась ошибка.
Вот код:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import ctypes
 
import glm
import pygame
from OpenGL.GL import *
from OpenGL.GL.shaders import *
from pygame.locals import *
 
vertexShaderSource = """
    attribute vec3 aPosition;
    uniform mat4 uMvpMatrix;
 
    void main()
    {
        gl_Position = uMvpMatrix * vec4(aPosition, 1.0);
    }
"""
 
fragmentShaderSource = """
    uniform vec3 uColor;
 
    void main()
    {
        gl_FragColor = vec4(uColor, 1.0);
    }
"""
 
        
class Model:
 
    def __init__(self, vertPositions, program, position, angle, scale, color):
        # Save the input variables
        self.program = program
        self.position = position
        self.angle = angle
        self.scale = scale
        self.color = color
        
        f = open(vertPositions, "r")
        #print(f.read())
        doc = f.read()
        
       
        spisok = doc.split('<float_array id=')
        spisok = spisok[1].split('-mesh-positions-array" count=')
        spisok = spisok[1].split('>')
        spisok = spisok[1].split('<')
        spisok = spisok[0].split()
        spisok = [float(i) for i in spisok]
        #print(len(spisok))
        #[1.0, -1.0, 0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0]
        
        #ищем список нормалей
        spisok2 = doc.split('<float_array id=')
        spisok2 = spisok2[2].split('-mesh-normals-array" count=')
        spisok2 = spisok2[1].split('>')
        spisok2 = spisok2[1].split('<')
        spisok2 = spisok2[0].split()
        spisok2 = [float(i) for i in spisok2]
        #print(spisok2)
        #[0, 0, 1, 0, 0, 1]
        
       
        spisok3 = doc.split('<p>')
        spisok3 = spisok3[1].split('<')
        spisok3 = spisok3[0].split()
        spisok3 = [int(i) for i in spisok3]
        #print(spisok3)
        #[1, 0, 0, 0, 2, 0, 3, 1, 1, 1, 2, 1]
        
        vertPositions = []
        normals = []
        k = 0
        for i in range(len(spisok3)):
            if k == 1:
                if spisok3[i] == 0:
                    normals.append(spisok2[0])
                    normals.append(spisok2[1])
                    normals.append(spisok2[2])
                else:
                    normals.append(spisok2[spisok3[i]*3])
                    normals.append(spisok2[spisok3[i]*3+1])
                    normals.append(spisok2[spisok3[i]*3+2])            
                k=0
            else:
                if spisok3[i] == 0:
                    vertPositions.append(spisok[0])
                    vertPositions.append(spisok[1])
                    vertPositions.append(spisok[2])
                else:
                    vertPositions.append(spisok[spisok3[i]*3])
                    vertPositions.append(spisok[spisok3[i]*3+1])
                    vertPositions.append(spisok[spisok3[i]*3+2])            
                k+=1        
 
        # Amount of vertices
        self.amountOfVertices = len(vertPositions) #// 2
 
        # Covert a Python list to a numpy array
        vertPositions = np.array(vertPositions, dtype=np.float32)
 
        # Create the vertex position buffer
        self.vertPosBuffer = glGenBuffers(1)
        # Bind the buffer
        glBindBuffer(GL_ARRAY_BUFFER, self.vertPosBuffer)
        # Copy data to the buffer
        glBufferData(GL_ARRAY_BUFFER, len(vertPositions) * 4,
            vertPositions, GL_STATIC_DRAW)
 
        # Get locations of the shader variables
        self.aPositionLocation = glGetAttribLocation(self.program, "aPosition")
        self.uColorLocation = glGetUniformLocation(self.program, "uColor")
        self.uMvpMatrixLocation = glGetUniformLocation(self.program, "uMvpMatrix")
 
    def draw(self, projViewMatrix):
        glUseProgram(self.program)
        # Bind the vertex position buffer
        glBindBuffer(GL_ARRAY_BUFFER, self.vertPosBuffer)
 
        # Setting up the aPosition attribute
        glEnableVertexAttribArray(self.aPositionLocation)
        glVertexAttribPointer(self.aPositionLocation, 2, GL_FLOAT, GL_FALSE,
            0, ctypes.c_void_p(0))
 
        # Send MVP-matrix to the vertex shader
        # Translate
        modelMatrix = glm.translate(glm.mat4(1), self.position)
        # Rotate
        modelMatrix = glm.rotate(modelMatrix, glm.radians(self.angle),
            glm.vec3(0, 0, 1))
        # Scale
        modelMatrix = glm.scale(modelMatrix, self.scale)
        mvpMatrix = projViewMatrix * modelMatrix
        glUniformMatrix4fv(self.uMvpMatrixLocation, 1, GL_FALSE,
            glm.value_ptr(mvpMatrix))
 
        # Send a color to the fragment shader
        glUniform3fv(self.uColorLocation, 1, glm.value_ptr(self.color))
 
        # Draw the model
        glDrawArrays(GL_TRIANGLES, 0, self.amountOfVertices)
 
 
def main():
    pygame.init()
    winWidth, winHeight = 300, 300
    display = (winWidth, winHeight)
 
    pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
 
    # Set a background color
    glClearColor(0.2, 0.2, 0.2, 1)
 
    # Triangle vertex positions
    
    triangleVertPositions = "untitled.dae" 
 
    # Create a shader program
    program = compileProgram(
       compileShader(vertexShaderSource, GL_VERTEX_SHADER),
       compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER))
 
    # Create models
    triangle = Model(
        vertPositions = triangleVertPositions,
        program = program,
        position = glm.vec3(50, 50, 0),
        angle = 20,
        scale = glm.vec3(50, 50, 1),
        color = glm.vec3(0.74, 0.58, 0.15))
    square = Model(
        vertPositions = squareVertPositions,
        program = program,
        position = glm.vec3(-50, 50, 0),
        angle = -30,
        scale = glm.vec3(50, 50, 1),
        color = glm.vec3(0.35, 0.78, 0.78))
 
    # Create the project and the view matrix
    #projMatrix = glm.ortho(-100, 100, -100, 100, 1, -1)
    projMatrix = glm.perspective(math.radians(45), winWidth/winHeight, 0.1, 1000)
    viewMatrix = glm.lookAt(
        glm.vec3(0, 0, 1),
        glm.vec3(0, 0, 0),
        glm.vec3(0, 1, 0))
    projViewMatrix = projMatrix * viewMatrix
 
    # Main loop
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
 
        # Clear the canvas
        glClear(GL_COLOR_BUFFER_BIT)
  
        # Draw models
        triangle.draw(projViewMatrix)
 
        # Flip the back the front screen buffer
        pygame.display.flip()
        # Wait 10 msec
        pygame.time.wait(10)
 
if __name__ == "__main__":
    main()
0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
11.09.2024, 19:06
Когда ошибка в коде, то показывается номер строки и текст ошибки. Пролистывайте код до номера строки, где ошибка и читайте текст ошибки. Я скачал ваш код и сразу его запустил. Мне вывелась такая ошибка:

Code
1
2
3
  File "main.py", line 39, in __init__
    f = open(vertPositions, "r")
FileNotFoundError: [Errno 2] No such file or directory: 'untitled.dae'
Я даже не стал переходить на строку 39, а сразу по тексту понял, что "нет такого файла или директории 'untitled.dae'", потому что я не копировал файлы моделей из прошлого проекта. Я копировал файлы моделей и запустил:

Code
1
2
3
  File "main.py", line 39, in __init__
    f = open(vertPositions, "r")
FileNotFoundError: [Errno 2] No such file or directory: 'untitled.dae'
Опять выдалось такое же сообщение об ошбики. Потому что прошлые файлы имели расширение ".txt", я исправил их на ".dae". Теперь выдаёт такую ошибку:

Code
1
2
3
  File "main.py", line 100, in __init__
    vertPositions = np.array(vertPositions, dtype=np.float32)
NameError: name 'np' is not defined
Здесь написано, что на строке 100 неопределено имя 'np'. Смотрю в начало файла и там действительно нет этого импорта:

Python
1
import numpy as np
Запускаю программу. Выдаёт ошибку:

Python
1
2
3
  File "main.py", line 173, in main
    vertPositions = squareVertPositions,
NameError: name 'squareVertPositions' is not defined
Смотрю на 173 строку, где 'squareVertPositions' не определено. Действительно, это имя встречается только один раз здесь:

Python
1
2
    square = Model(
        vertPositions = squareVertPositions,
У вас в коде есть переменная "triangleVertPositions", которая, судя по названию должна хранить вершины модели треугольника, то вы в неё сохраняете имя объекта:

Python
1
triangleVertPositions = "untitled.dae"
У вас нет треугольника в коде. Нужно переименовать "triangleVertPositions", например, в "untitledVertPositions" и в этот список загрузить вершины из файла "untitled.dae". Вы это же делали раньше.
0
175 / 10 / 1
Регистрация: 05.08.2024
Сообщений: 73
11.09.2024, 20:14  [ТС]
Понял. Иду исправлять. Вот это я невнимательный
0
175 / 10 / 1
Регистрация: 05.08.2024
Сообщений: 73
12.09.2024, 17:42  [ТС]
Здравствуйте! Я решил ошибки программы, но появилась новая: отсутствует фигура, а также при изменении вектора позиции изменяется цвет фона
Вот код:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
import ctypes
 
import glm
import pygame
from OpenGL.GL import *
from OpenGL.GL.shaders import *
from pygame.locals import *
import numpy as np
import math
 
vertexShaderSource = """
    attribute vec3 aPosition;
    uniform mat4 uMvpMatrix;
 
    void main()
    {
        gl_Position = uMvpMatrix * vec4(aPosition, 1.0);
    }
"""
 
fragmentShaderSource = """
    uniform vec3 uColor;
 
    void main()
    {
        gl_FragColor = vec4(uColor, 1.0);
    }
"""
 
        
class Model:
 
    def __init__(self, vertPositions, program, position, angle, scale, color):
        # Save the input variables
        self.program = program
        self.position = position
        self.angle = angle
        self.scale = scale
        self.color = color
        
        f = open(vertPositions, "r")
        #print(f.read())
        doc = f.read()
        
        #ищем список координат
        #ищем список координат
        spisok = doc.split('<float_array id=')
        spisok = spisok[1].split('-mesh-positions-array" count=')
        spisok = spisok[1].split('>')
        spisok = spisok[1].split('<')
        spisok = spisok[0].split()
        spisok = [float(i) for i in spisok]
        #print(len(spisok))
        #[1.0, -1.0, 0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0]
        
        #ищем список нормалей
        spisok2 = doc.split('<float_array id=')
        spisok2 = spisok2[2].split('-mesh-normals-array" count=')
        spisok2 = spisok2[1].split('>')
        spisok2 = spisok2[1].split('<')
        spisok2 = spisok2[0].split()
        spisok2 = [float(i) for i in spisok2]
        #print(spisok2)
        #[0, 0, 1, 0, 0, 1]
        
        #ищем список индекс
        spisok3 = doc.split('<p>')
        spisok3 = spisok3[1].split('<')
        spisok3 = spisok3[0].split()
        spisok3 = [int(i) for i in spisok3]
        #print(spisok3)
        #[1, 0, 0, 0, 2, 0, 3, 1, 1, 1, 2, 1]
        
        vertPositions = []
        normals = []
        k = 0
        for i in range(len(spisok3)):
            if k == 1:
                if spisok3[i] == 0:
                    normals.append(spisok2[0])
                    normals.append(spisok2[1])
                    normals.append(spisok2[2])
                else:
                    normals.append(spisok2[spisok3[i]*3])
                    normals.append(spisok2[spisok3[i]*3+1])
                    normals.append(spisok2[spisok3[i]*3+2])            
                k=0
            else:
                if spisok3[i] == 0:
                    vertPositions.append(spisok[0])
                    vertPositions.append(spisok[1])
                    vertPositions.append(spisok[2])
                else:
                    vertPositions.append(spisok[spisok3[i]*3])
                    vertPositions.append(spisok[spisok3[i]*3+1])
                    vertPositions.append(spisok[spisok3[i]*3+2])            
                k+=1        
 
        # Amount of vertices
        self.amountOfVertices = len(vertPositions) #// 2
 
        # Covert a Python list to a numpy array
        vertPositions = np.array(vertPositions, dtype=np.float32)
 
        # Create the vertex position buffer
        self.vertPosBuffer = glGenBuffers(1)
        # Bind the buffer
        glBindBuffer(GL_ARRAY_BUFFER, self.vertPosBuffer)
        # Copy data to the buffer
        glBufferData(GL_ARRAY_BUFFER, len(vertPositions) * 4,
            vertPositions, GL_STATIC_DRAW)
 
        # Get locations of the shader variables
        self.aPositionLocation = glGetAttribLocation(self.program, "aPosition")
        self.uColorLocation = glGetUniformLocation(self.program, "uColor")
        self.uMvpMatrixLocation = glGetUniformLocation(self.program, "uMvpMatrix")
 
    def draw(self, projViewMatrix):
        glUseProgram(self.program)
        # Bind the vertex position buffer
        glBindBuffer(GL_ARRAY_BUFFER, self.vertPosBuffer)
 
        # Setting up the aPosition attribute
        glEnableVertexAttribArray(self.aPositionLocation)
        glVertexAttribPointer(self.aPositionLocation, 2, GL_FLOAT, GL_FALSE,
            0, ctypes.c_void_p(0))
 
        # Send MVP-matrix to the vertex shader
        # Translate
        modelMatrix = glm.translate(glm.mat4(1), self.position)
        # Rotate
        modelMatrix = glm.rotate(modelMatrix, glm.radians(self.angle),
            glm.vec3(0, 0, 1))
        # Scale
        modelMatrix = glm.scale(modelMatrix, self.scale)
        mvpMatrix = projViewMatrix * modelMatrix
        glUniformMatrix4fv(self.uMvpMatrixLocation, 1, GL_FALSE,
            glm.value_ptr(mvpMatrix))
 
        # Send a color to the fragment shader
        glUniform3fv(self.uColorLocation, 1, glm.value_ptr(self.color))
 
        # Draw the model
        glDrawArrays(GL_TRIANGLES, 0, self.amountOfVertices)
 
 
def main():
    pygame.init()
    winWidth, winHeight = 300, 300
    display = (winWidth, winHeight)
 
    pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
 
    # Set a background color
    glClearColor(0.2, 0.2, 0.2, 1)
 
    # Triangle vertex positions
    
    triangleVertPositions = "untitled.dae" 
 
    # Create a shader program
    program = compileProgram(
       compileShader(vertexShaderSource, GL_VERTEX_SHADER),
       compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER))
 
    # Create models
    triangle = Model(
        vertPositions = triangleVertPositions,
        program = program,
        position = glm.vec3(0, 0, 0),
        angle = 20,
        scale = glm.vec3(50, 50, 1),
        color = glm.vec3(0.74, 0.58, 0.15))
    # Create the project and the view matrix
    #projMatrix = glm.ortho(-100, 100, -100, 100, 1, -1)
    projMatrix = glm.perspective(math.radians(45), winWidth/winHeight, 0.1, 1000)
    viewMatrix = glm.lookAt(
        glm.vec3(0, 0, 1),
        glm.vec3(0, 0, 0),
        glm.vec3(0, 1, 0))
    projViewMatrix = projMatrix * viewMatrix
 
    # Main loop
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
 
        # Clear the canvas
        glClear(GL_COLOR_BUFFER_BIT)
  
        # Draw models
        triangle.draw(projViewMatrix)
 
        # Flip the back the front screen buffer
        pygame.display.flip()
        # Wait 10 msec
        pygame.time.wait(10)
 
if __name__ == "__main__":
    main()
0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
12.09.2024, 18:18
Программа ошибок не выдаёт. Показывает оранжевый экран. Предлагаю детально разобраться по шагам. Для быстрого воспроизведения проблемы прикрепляю архив с программой и моделями, а позже начну разбирать программу.

Название: dcf9e06cf298e94962b9d76ebf81065e7bf2650b.png
Просмотров: 82

Размер: 2.8 Кб



Миниатюры
0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
12.09.2024, 21:04
Я не знал, что за объект вы загружаете из файла под именем "untitled.dae", поэтому я импортировал этот файл в Blender. Оказалось, что это сфера. Я переименовал "untitled.dae" в "sphere.dae". Предлагаю вам тоже это сделать в своём проекте.

Сфера - это слишком сложный объект для тестирования. Надо загружать "plane.dae", то есть плоскость. У неё мало вершин, поэтому проще будет отлаживать. Вы передаёте имя файла при создании объекта здесь:

Python
1
2
3
4
5
6
7
8
9
10
    triangleVertPositions = "plane.dae"
 
    # Create models
    triangle = Model(
        vertPositions = triangleVertPositions,
        program = program,
        position = glm.vec3(0, 0, 0),
        angle = 20,
        scale = glm.vec3(50, 50, 1),
        color = glm.vec3(0.74, 0.58, 0.15))
А потом вы в конструкторе класса Model читаете парсите данные:

Python
1
2
3
4
5
6
7
8
9
10
11
    def __init__(self, vertPositions, program, position, angle, scale, color):
        # Save the input variables
        self.program = program
        self.position = position
        self.angle = angle
        self.scale = scale
        self.color = color
        
        f = open(vertPositions, "r")
        #print(f.read())
        doc = f.read()
Это неправильно! Нужно распарсить данные до создания экземпляра Model, а при создании Model надо передавать массив вершин. Вот этот код нужно перенести в main():

Python
1
2
3
    f = open(vertPositions, "r")
    #print(f.read())
    doc = f.read()
Надо поменять имена. Название "vertPositions" означает "vertex positions", то есть это "позиции вершин". Нужно заменить имя "triangle" на "plane". Должно быть так:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def main():
    pygame.init()
 
    # ...
 
    f = open("plane.dae", "r")
    doc = f.read()
 
    #ищем список координат
    #ищем список координат
    spisok = doc.split('<float_array id=')
    spisok = spisok[1].split('-mesh-positions-array" count=')
    spisok = spisok[1].split('>')
    # ...
 
    # Create models
    plane = Model(
        vertPositions = vertPositions,
        program = program,
        position = glm.vec3(0, 0, 0),
        angle = 20,
        scale = glm.vec3(50, 50, 1),
        color = glm.vec3(0.74, 0.58, 0.15))
В главном цикле поменяйте "triangle" на "plane":

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    # Main loop
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
 
        # Clear the canvas
        glClear(GL_COLOR_BUFFER_BIT)
  
        # Draw models
        plane.draw(projViewMatrix)
 
        # Flip the back the front screen buffer
        pygame.display.flip()
        # Wait 10 msec
        pygame.time.wait(10)
Камера слишком близко. У неё была позиция (0, 0, 1), а сфера имела размер (50, 50, 50), то есть камера оказалась внутри сферы, а сфера оранжевого цвета, поэтому был оранжевый цвета на весь холст.

Я убрал класс Model в отдельный файл "model.py". Так удобнее. А ещё я убрал загрузку данных в отдельный файл "load_data.py". Загрузил два объекта - плоскость и куб. Скачайте прикреплённый архив и добавьте остальные объекты. Меняйте параметры "position" и "scale", а так же можете поменять цвета для новых объектов. Для плоскости надо сделать большой размер, чтобы это была земля, куда будут отображаться тени в следующей версии программы.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    plane = Model(
        vertPositions = planeVertexPositions,
        program = program,
        position = glm.vec3(-2, 0, 0),
        angle = 0,
        scale = glm.vec3(50, 50, 1),
        color = glm.vec3(0.74, 0.58, 0.15))
 
    cube = Model(
        vertPositions = planeVertexPositions,
        program = program,
        position = glm.vec3(2, 0, 0),
        angle = 0,
        scale = glm.vec3(20, 20, 1),
        color = glm.vec3(0.2, 0.58, 0.15))
В классе Model нужно заменить 2 на 3, потому что данные позиций вершин имеет 3 значения (x, y, z):

Python
1
2
glVertexAttribPointer(self.aPositionLocation, 3, GL_FLOAT, GL_FALSE,
    0, ctypes.c_void_p(0))
Замените этот простой шейдер на шейдер с освещением, где применяются нормали. Был такой пример. Берите этот пример. Ставьте "pugixml": https://pypi.org/project/pugixml/

Code
1
pip install pugixml
Эту библиотеку я применил для парсинга XML. Я использовал этот пример для парсинга DAE с помощью языка запросов XPath: https://stackoverflow.com/a/34629538/4159530



Кликните здесь для просмотра всего текста
Вложения
Тип файла: zip dae-loader.zip (39.4 Кб, 0 просмотров)
0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
12.09.2024, 23:31
Я немного усовершенствовал пример из предыдущего сообщения. Добавил освещение. Передал нормали в Model:



Убрал модели в отдельную папку "assets/models", чтобы они не мешались среди файлов программы. Убрал код шейдеров отдельные файлы в папку "assets/shaders", чтобы "main.py" поменьше и чтобы работала подсветка синтаксиса в шейдерах. Теперь файлы с кодом не лежат в перемешку с файлами 3D-моделей. Использую редактор кода Sublime Text 4:

Название: e319270f83d53fd54f352ca8efcf69f94a58290c.png
Просмотров: 75

Размер: 1.5 Кб



Прикрепляйте программу архивом, когда она много файловая и/или содержит ассеты. Так всем удобнее. Скачал и запустил, или в архив добавил и прикрепил.

Вот что нужно сделать:
  • Скачайте пример dae-loader.zip, который прикреплён к данному сообщению
  • Загрузите "monkey.dae" и "sphere.dae" по аналогии с "cube.dae" и "plane.dae", так, чтобы объекты не касались друг друга, то есть задайте им нужные позиции:

    Python
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
        planeVertexPositions, planeNormals = loadData("plane.dae")
        cubeVertexPositions, cubeNormals = loadData("cube.dae")
     
        plane = Model(
            vertPositions = planeVertexPositions,
            program = program,
            position = glm.vec3(-2, 0, 0),
            angle = 0,
            scale = glm.vec3(5, 5, 5),
            color = glm.vec3(0.74, 0.58, 0.15))
     
        cube = Model(
            vertPositions = cubeVertexPositions,
            program = program,
            position = glm.vec3(2, 2, 0),
            angle = 0,
            scale = glm.vec3(2, 2, 2),
            color = glm.vec3(0.2, 0.58, 0.15))
  • Нарисуйте добавленные 3D-модели, вызвав их методы draw() в главном цикле, по аналогии с "cube" и "plane":
    Python
    1
    2
    3
    4
    5
    6
    
            # Clear the canvas
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
      
            # Draw models
            plane.draw(projViewMatrix)
            cube.draw(projViewMatrix)

Миниатюры
Вложения
Тип файла: zip dae-loader.zip (40.7 Кб, 0 просмотров)
1
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
13.09.2024, 18:08
Добавил тени к предыдущему примеру. Код теней взял из примера прошлой темы. Загрузил модель Хагрида из игры "Гарри Поттер и философский камень". Модель есть в свободном доступе здесь.

Название: dae-loader-and-shadows.gif
Просмотров: 69

Размер: 436.9 Кб
Вложения
Тип файла: zip dae-loader-and-shadows-opengl21-pygame.zip (58.0 Кб, 3 просмотров)
1
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
28.09.2024, 16:29
Лучший ответ Сообщение было отмечено 8Observer8 как решение

Решение

Отвлёк я вас от темы. Хотел, чтобы вы научились загружать текстурированные объекты из Collada. По теме я попытался ответить в сообщении #34, где я привёл пример:
  • вращения камеры зажатой левой кнопкой мышкой вокруг объекта
  • перемещения камеры правой кнопкой
  • отдаления и приближения с помощью колёсика мыши
, то есть "Orbit Controls". Но потом я понял, что вам нужен тип управления "Fly Controls", то есть
  • перемещение камеры в направление взгляда с помощью W и колёсика мыши (или стрелки верх)
  • перемещение камеры назад с помощью S и колёсика мыши (или стрелки вниз)
  • перемещение камеры влево и вправо с помощью AD (или стрелок влево и вправо)
  • вращение камеры с помощью зажатой левой кнопки мыши вокруг точки своего положения, для осмотра вокруг
Теперь я уверен, что это то, что вам нужно. Думаю, прикреплённый пример можно считать решением темы.

Команды для установки необходимых пакетов и запуска примера:
Code
1
2
pip install Pygame PyOpenGL PyGLM numpy Pillow pugixml
py main.py


Миниатюра
Вложения
Тип файла: zip textured-hagrid-and-fly-controls-opengl21-pygame.zip (589.2 Кб, 3 просмотров)
0
1975 / 831 / 115
Регистрация: 01.10.2012
Сообщений: 5,043
Записей в блоге: 2
28.09.2024, 17:29
Цитата Сообщение от 8Observer8 Посмотреть сообщение
то есть "Orbit Controls".
Обычно камера задается позицией и точкой куда она смотрит (reference). Orbit - это когда меняется позиция камеры, а reference остается той же (т.е. облет камерой). Обычно и длина вектора position - reference остается той же.
0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
28.09.2024, 17:49
Igor3D, что конкретно я ошибся? Управление камерой в Blender разве не является типом "Orbit Controls"? Я взял название "Orbit Controls" из Three.js: OrbitControls – three.js docs. Если разработчики Three.js не ошиблись с названием и логикой, то это управление камерой характеризуется тем, что камера смотрит на target и перемещается по орбите вокруг target, и постоянно смотрит на target. А название "Fly Controls" я тоже взял из Three.js: FlyControls – three.js docs. Не понимаю, в чём я ошибаюсь.
0
1975 / 831 / 115
Регистрация: 01.10.2012
Сообщений: 5,043
Записей в блоге: 2
28.09.2024, 18:33
Цитата Сообщение от 8Observer8 Посмотреть сообщение
это управление камерой характеризуется тем, что камера смотрит на target и перемещается по орбите вокруг target, и постоянно смотрит на target.
Да, так и есть
Цитата Сообщение от 8Observer8 Посмотреть сообщение
что конкретно я ошибся?
Это не ошибка. Если данные были заданы удачно (position + reference), то весь ответ был бы пол-странички: меняем position и вызываем lookAt, это небольшое изменение в коде стартового поста

Не по теме:

Цитата Сообщение от 8Observer8 Посмотреть сообщение
Отвлёк я вас от темы. Хотел, чтобы вы научились загружать текстурированные объекты из Collada.
Правильная мысль, без загрузки объектов - тупик. А что отвлекли - переживет :)

0
175 / 10 / 1
Регистрация: 05.08.2024
Сообщений: 73
29.09.2024, 18:33  [ТС]
Здравствуйте! Извините, что долго не появлялся в сети, не было доступа к компьютеру. А во время отсутствия пк решил чуток углубиться в OpenGL. Хочу спросить, не легче использовать функцию GL_LIGHTING, или она не будет работать при шейдерах?
0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
29.09.2024, 19:18
Цитата Сообщение от Daniil_G Посмотреть сообщение
она не будет работать при шейдерах?
Не будет. Тень вы всё равно не получите, которая будет отбрасываться на плоскость, а то в том затенении, которое возникает на объектах, нет ничего сложного, так как оно считается одной строчкой, через скалярное произведение:

glSlang
1
vDot = max(dot(normalize(normal.xyz), lightDirection), ambient);
"normal" и "lightDirection" - это нормализованные векторы, то есть их длина равна единице. Определяющее значение играет косинус угла между этими векторами. Он может быть от -1 до 1. Функция dot() вернёт 1 когда угол между векторами равен 0, то есть векторы направлены в сторону. Если вектора под 90 градусов, то вернёт 0, а если 180 - то вернёт -1. А так, как используется функция max(), то в итоге будет значение между ambient и 1, а ambient равен 0.3. Это сделано, чтобы в неосвещённой области был не чёрный цвет, а цвет объекта, но только 30% от него.

Расчёт коэффициента vDot происходит в вершинном шейдере (а можно было бы считать vDot в фрагментом шейдере, то получилось бы не направленное, а точечное освещение, как от лампочки). Эта переменная со словом "varying", то есть это значение будет интерполироваться между вершинами. В фрагментом шейдере для промежуточных фрагментов, то есть которые находятся между вершинами, будет интерполированное значение vDot. Это значит, что у треугольника в вершинах может быть разный vDot, так как нормали могут быть разными - они могут быть усреднены, см. кнопка "Smooth" в Blender. То есть если у треугольника разные нормали, то и vDot будет разный, а промежуточные фрагменты получат разный vDot. Цвет для всех промежуточных фрагментов треугольника будет считаться со своим vDot вот так:

glSlang
1
2
3
4
5
6
7
8
9
10
11
12
// ...
 
const vec3 lightColor = vec3(1.0, 1.0, 1.0);
 
varying float vDot;
 
void main()
{
    vec4 color = texture2D(uSampler, vec2(vTexCoord.s, 1.0 - vTexCoord.t));
    vec3 diffuse = lightColor * color.rgb * vDot;
    gl_FragColor = vec4(diffuse, 1.0);
}
Вот эта операция: "vec2(vTexCoord.s, 1.0 - vTexCoord.t)" нужна, чтобы перевернуть текстуру по Y координате, то есть сделать "flip Y axis". Бывает, что не надо переворачивать текстуру, поэтому можно написать проще: texture2D(uSampler, vTexCoord). Это зависит от модели. Вот у той модели Хагрида текстура перевёрнутая, поэтому я сделал "flip Y axis".

В этой строке: "vec3 diffuse = lightColor * color.rgb * vDot;" итоговый цвет рассчитывается из белого цвета освещения, цвет: (1, 1, 1), то есть белый цвет, это когда все компоненты равны единице. Можно изменить белый цвет, на какой-нибудь красноватый, если светит красноватый источник света. Второй множитель - это цвет текстуры - color.rgb, то есть это пиксель текстуры и у него есть цвет "RGB". Текстура накладывается на треугольник. Текстурная координата vTexCoord интерполируется между вершинами треугольника. Переменная uSampler хранит идентификатор текстуры. Функция texture2D() принимает идентификатор текстуры и интерполированную текстурную координату vTexCoord, на основании этих параметров texture2D() возвращает цвет текстуры в виде RGB. В этом произведении "lightColor * color.rgb * vDot" коэффициент vDot хранит значение от 0.3 до 1, то есть он определяет будет ли цвет на 100%, если vDot = 1, на 30%, если vDot = 0.3, либо какое-то промежуточное значение между 0.3 и 1, например, 0.55, 0.78 и т.д.
1
30.09.2024, 02:07

Не по теме:

Цитата Сообщение от 8Observer8 Посмотреть сообщение
Расчёт коэффициента vDot происходит в вершинном шейдере (а можно было бы считать vDot в фрагментом шейдере, то получилось бы не направленное, а точечное освещение, как от лампочки).
Направленное (наверно имеется ввиду параллельный источник/модель) или точечное - целиком зависит от lightDirection, без разницы в каком шейдере считать. Расчет освещенности в вертексах с последующей интерполяцией (Gourand Shading) все успешно забыли лет 20 назад, сейчас это дань истории :)

0
9949 / 2949 / 497
Регистрация: 05.10.2013
Сообщений: 8,025
Записей в блоге: 242
30.09.2024, 04:04
Цитата Сообщение от Igor3D Посмотреть сообщение
без разницы в каком шейдере считать
Да, верно, не в этом отличие между освещением параллельными лучами и точечным освещением. Спасибо, что поправили. Когда скалярное произведение считается в вершинном шейдере, то это Gouraud shading, а когда в фрагментном, то это Phong shading. Можно погуглить, чем они отличаются. Например, ответ на StackOverflow (там есть две картинки с отличиями), а это перевод Google Translate первой части ответа:

В то время как при затенении по Гуро свет рассчитывается по вершинам (шейдер вершин), при затенении по Фонгу свет рассчитывается по фрагментам (шейдер фрагментов).
Таким образом, затенение по Гуро рассчитывает свет для вершин (углов) примитива и интерполирует свет для фрагментов, охватываемых примитивом.
При затенении по Фонгу свет рассчитывается отдельно для каждого фрагмента.
Оставлю пример точечного освещения с затенением по Фонгу в виде пары шейдеров, может быть кому-то пригодится:

texture.vert

glSlang
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
attribute vec4 aPosition;
attribute vec4 aNormal;
attribute vec2 aTexCoord;
 
uniform mat4 uMvpMatrix;
uniform mat4 uModelMatrix;
uniform mat4 uNormalMatrix;
 
varying vec3 vPosition;
varying vec3 vNormal;
varying vec2 vTexCoord;
 
void main()
{
    gl_Position = uMvpMatrix * aPosition;
    vPosition = vec3(uModelMatrix * aPosition);
    vNormal = normalize(vec3(uNormalMatrix * aNormal));
    vTexCoord = aTexCoord;
}
texture.frag

glSlang
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
precision mediump float;
 
const vec3 lightColor = vec3(1.0, 1.0, 1.0);
const vec3 lightPosition = vec3(2.0, 5.0, 30.0);
const float ambient = 0.3;
 
varying vec3 vPosition;
varying vec3 vNormal;
varying vec2 vTexCoord;
 
uniform sampler2D uSampler;
 
void main()
{
    vec4 color = texture2D(uSampler, vTexCoord);
    vec3 normal = normalize(vNormal);
    vec3 lightDirection = normalize(lightPosition - vPosition);
    float nDotL = max(dot(lightDirection, normal), ambient);
    vec3 diffuse = lightColor * color.rgb * nDotL;
    gl_FragColor = vec4(diffuse, color.a);
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
30.09.2024, 04:04
Помогаю со студенческими работами здесь

Перемещение камеры как в песочнице
Я хочу реализовать перемещение как в песочнице, когда зажимаешь левую кнопку мыши тянешь ее и камера тоже перемещается.

Как правильно настроить перемещение камеры?
Добрый день. Недавно купила геймпад китайский, выглядит как xbox 360. Компьютером и всеми играми как 360 определяется, все кнопки работают,...

Перемещение камеры, как в редакторе unity в окне Scene
Всем привет! Подскажите, пожалуйста, как реализовать точно такое же перемещение камеры как в самом unity в окне Scene, когда мы зажимаем...

Перемещение камеры = -перемещение сцены?
Прочитала в redbook что переместить камеру можно 2 способами: переместить саму камеру в прямом направлении или переместить все объекты в...

Как сделать перемещение нескольких файлов с заменой? И как это сделать проще?
Как сделать перемещение нескольких файлов с заменой? Например я ввожу в текстбокс название файлов, потом эти файлы переношу в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
[golang] Алгоритм «Хак Госпера»
alhaos 17.05.2026
Алгоритм «Хак Госпера» Хак Госпера (Gosper's Hack) — алгоритм нахождения следующего по величине числа с тем же количеством установленных бит. Придуман Биллом Госпером в 1970-х, опубликован в. . .
Рисование бинарного древа до 6-го колена на js, svg.
russiannick 17.05.2026
<svg width="335" height="240" viewBox="0 0 335 240" fill="#e5e1bb"> <style> <!]> </ style> <g id="bush"> </ g> </ svg> function fn(){ let rost;/ / высота древа let xx=165,yy=210,w=256;
FSharp: interface of module
DevAlt 16.05.2026
Интерфейс модуля F# позволяет управлять доступностью членов, содержащихся в реализации модуля. По-умолчанию все члены модуля доступны: module Foo let x = 10 let boo () = printfn "boo" . . .
Хитросплетение родственных связей пантеона греческих богов.
russiannick 14.05.2026
Однооконник, позволяющий узреть и изучить отдельных героев древней Греции. <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible". . .
[golang] Угол между стрелками часов
alhaos 12.05.2026
По заданным значениям часа и минуты необходимо определить значение меньшего угла между стрелками аналогового циферблата часов. import "math" func angleClock(hour int, minutes int) float64 { . . .
Debian 13: Установка Lazarus QT5
ВитГо 09.05.2026
Эта инструкция моя компиляция инструкций volvo https:/ / www. cyberforum. ru/ blogs/ 203668/ 10753. html и его же старой инструкции по установке Lazarus с gtk2. . .
Нейросеть на алгоритме "эстафета хвоста" как перспектива.
Hrethgir 06.05.2026
На десерт, когда запущу сервер. Статья тут https:/ / habr. com/ ru/ articles/ 1030914/ . Автор я сам, нейросеть только помогает в вопросах которые мне не известны - не знаю людей которые знали-бы. . .
Асинхронный приём данных из COM-порта
Argus19 01.05.2026
Асинхронный приём данных из COM-порта Купил на aliexpress термопринтер QR701. Он оказался странным. Поключил к Arduino Nano. Был очень удивлён. Наотрез отказывается печатать русские буквы. Чтобы. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru