OpenGL 对象的颜色和运动没有正确交替
Color and movement of OpenGL object does not alternate properly
我的程序是一个房间,中间有一个光源(球体)。
我想制作一个 "disco" 模式,使球体沿 x 轴左右移动。并且同时在红色和蓝色之间交替它的颜色。
这是我启用该模式的代码部分。 g_disco_mode
是选择模式后为真的变量。
static void update_scene()
{
...
// Disco mode
if (g_disco_mode)
{
bool movement_increase = true;
bool color_increase = true;
float floor = -0.1f;
float ceiling = 1.0f;
float increment = 0.01f;
// Movement of spotlight
if (movement_increase == true && g_lightProperties.direction[0] <= ceiling)
{
g_lightProperties.direction[0] += increment;
if (g_lightProperties.direction[0] >= ceiling) { movement_increase = false; }
}
if (movement_increase == false && g_lightProperties.direction[0] >= floor)
{
g_lightProperties.direction[0] -= increment;
if (g_lightProperties.direction[0] <= floor) { movement_increase = true; }
}
// Changing of color
g_spotlight_ambient[0] += 0.01f;
if (color_increase == true && g_spotlight_ambient[0] <= ceiling)
{
g_spotlight_ambient[0] += increment;
if (g_spotlight_ambient[0] >= ceiling) { color_increase = false; }
}
if (color_increase == false && g_spotlight_ambient[0] >= floor)
{
g_spotlight_ambient[0] -= increment;
if (g_spotlight_ambient[0] <= floor) { color_increase = true; }
}
}
}
我编写了这部分代码,使球体向右移动直到碰到 ceiling
,然后向左移动直到碰到 floor
。这是通过递增和递减 g_lightProperties.direction
来完成的。
颜色的变化也以类似的方式工作。然而,当我 运行 我的程序时,球体向右移动直到它碰到 ceiling
然后停止。它不会向左移动。对于颜色,它只是不断变红,不会变回蓝色。为什么会这样?
我的程序
// Values for spotlight
glm::vec3 g_spotlight_ambient(0.2f, 0.2f, 0.2f);
glm::vec3 g_spotlight_diffuse(0.0f, 0.5f, 1.0f);
glm::vec3 g_spotlight_specular(0.0f, 0.5f, 1.0f);
bool g_switchOn = true; // toggle the light on/off
bool g_disco_mode = false; // makes the lights move around and change color
static void init(GLFWwindow* window)
{
...
// initialise light and material properties
g_lightProperties.position = glm::vec4(0.0f, 2.0f, 0.0f, 1.0f);
g_lightProperties.ambient = glm::vec4(g_spotlight_ambient[0], g_spotlight_ambient[1], g_spotlight_ambient[2], 1.0f);
g_lightProperties.diffuse = glm::vec4(g_spotlight_diffuse[0], g_spotlight_diffuse[1], g_spotlight_diffuse[2], 1.0f);
g_lightProperties.specular = glm::vec4(g_spotlight_specular[0], g_spotlight_specular[1], g_spotlight_specular[2], 1.0f);
g_lightProperties.shininess = 10.0f;
g_lightProperties.attenuation = glm::vec3(1.0f, 0.0f, 0.0f);
g_lightProperties.cutoffAngle = 100.0f;
g_lightProperties.direction = glm::vec3(0.0f, -1.0f, 0.0f);
...
}
// function used to update the scene
static void update_scene()
{
static float rotateAngle = 0.0f;
static float cutOffAngle = g_lightProperties.cutoffAngle;
rotateAngle -= 1.0f;
// update model matrix
g_modelMatrix_mesh[0] = glm::rotate(glm::radians(rotateAngle), glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(-0.4f, 0.1f, 0.0f)) * glm::scale(glm::vec3(0.3f, 0.3f, 0.3f));
g_modelMatrix_mesh[1] = glm::rotate(glm::radians(rotateAngle), glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(0.4f, 0.3f, 0.0f)) * glm::scale(glm::vec3(0.2f, 0.2f, 0.2f));
g_modelMatrix_mesh[2] = glm::translate(g_lightProperties.direction)
* glm::translate(glm::vec3(0.0f, 2.0f, 0.0f)) * glm::scale(glm::vec3(0.2f, 0.2f, 0.2f));
// update spotlight
g_lightProperties.ambient = glm::vec4(g_spotlight_ambient[0], g_spotlight_ambient[1], g_spotlight_ambient[2], 1.0f);
g_lightProperties.diffuse = glm::vec4(g_spotlight_diffuse[0], g_spotlight_diffuse[1], g_spotlight_diffuse[2], 1.0f);
g_lightProperties.specular = glm::vec4(g_spotlight_specular[0], g_spotlight_specular[1], g_spotlight_specular[2], 1.0f);
// Disco mode
if (g_disco_mode)
{
bool movement_increase = true;
bool color_increase = true;
float floor = -0.1f;
float ceiling = 1.0f;
float increment = 0.01f;
// Movement of spotlight
if (movement_increase == true && g_lightProperties.direction[0] <= ceiling)
{
g_lightProperties.direction[0] += increment;
if (g_lightProperties.direction[0] >= ceiling) { movement_increase = false; }
}
if (movement_increase == false && g_lightProperties.direction[0] >= floor)
{
g_lightProperties.direction[0] -= increment;
if (g_lightProperties.direction[0] <= floor) { movement_increase = true; }
}
// Changing of color
g_spotlight_ambient[0] += 0.01f;
if (color_increase == true && g_spotlight_ambient[0] <= ceiling)
{
g_spotlight_ambient[0] += increment;
if (g_spotlight_ambient[0] >= ceiling) { color_increase = false; }
}
if (color_increase == false && g_spotlight_ambient[0] >= floor)
{
g_spotlight_ambient[0] -= increment;
if (g_spotlight_ambient[0] <= floor) { color_increase = true; }
}
}
}
// function used to render the scene
static void render_scene()
{
glBindVertexArray(g_VAO[0]); // make VAO active
// Material Properties - Planes
glUniform4fv(g_materialAmbientIndex, 1, &g_materialProperties.ambient[0]);
glUniform4fv(g_materialDiffuseIndex, 1, &g_materialProperties.diffuse[0]);
glUniform4fv(g_materialSpecularIndex, 1, &g_materialProperties.specular[0]);
glUniform4fv(g_lightPositionIndex, 1, &g_lightProperties.position[0]);
glUniform4fv(g_lightAmbientIndex, 1, &g_lightProperties.ambient[0]);
glUniform4fv(g_lightDiffuseIndex, 1, &g_lightProperties.diffuse[0]);
glUniform4fv(g_lightSpecularIndex, 1, &g_lightProperties.specular[0]);
glUniform1fv(g_lightShininessIndex, 1, &g_lightProperties.shininess);
glUniform3fv(g_lightAttenuationIndex, 1, &g_lightProperties.attenuation[0]);
glUniform1fv(g_lightCutoffAngleIndex, 1, &g_lightProperties.cutoffAngle);
glUniform3fv(g_lightDirectionIndex, 1, &g_lightProperties.direction[0]);
...
}
int main(void)
{
TwBar *TweakBar; // pointer to a tweak bar
...
// initialise AntTweakBar
TwInit(TW_OPENGL_CORE, NULL);
// give tweak bar the size of graphics window
TwWindowSize(g_windowWidth, g_windowHeight);
TwDefine(" TW_HELP visible=false "); // disable help menu
TwDefine(" GLOBAL fontsize=3 "); // set large font size
// create a tweak bar
TweakBar = TwNewBar("Main");
TwDefine(" Main label='Controls' refresh=0.02 text=light size='220 600' ");
// create display entries
TwAddVarRW(TweakBar, "Wireframe", TW_TYPE_BOOLCPP, &g_wireFrame, " group='Display' ");
// display a separator
TwAddSeparator(TweakBar, NULL, NULL);
// create spotlight entries
TwAddVarRW(TweakBar, "Cutoff", TW_TYPE_FLOAT, &g_lightProperties.cutoffAngle, " group='Spotlight' min=-180.0 max=180.0 step=1.0 ");
TwAddVarRW(TweakBar, "Direction: x", TW_TYPE_FLOAT, &g_lightProperties.direction[0], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
TwAddVarRW(TweakBar, "Direction: y", TW_TYPE_FLOAT, &g_lightProperties.direction[1], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
TwAddVarRW(TweakBar, "Direction: z", TW_TYPE_FLOAT, &g_lightProperties.direction[2], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
// create transformation entries
TwAddVarRW(TweakBar, "A Red", TW_TYPE_FLOAT, &g_spotlight_ambient[0], " group='Ambient' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "A Green", TW_TYPE_FLOAT, &g_spotlight_ambient[1], " group='Ambient' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "A Blue", TW_TYPE_FLOAT, &g_spotlight_ambient[2], " group='Ambient' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "D Red", TW_TYPE_FLOAT, &g_spotlight_diffuse[0], " group='Diffuse' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "D Green", TW_TYPE_FLOAT, &g_spotlight_diffuse[1], " group='Diffuse' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "D Blue", TW_TYPE_FLOAT, &g_spotlight_diffuse[2], " group='Diffuse' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "S Red", TW_TYPE_FLOAT, &g_spotlight_specular[0], " group='Specular' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "S Green", TW_TYPE_FLOAT, &g_spotlight_specular[1], " group='Specular' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "S Blue", TW_TYPE_FLOAT, &g_spotlight_specular[2], " group='Specular' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "Light", TW_TYPE_BOOLCPP, &g_switchOn, " group='Toggle ON/OFF' ");
TwAddVarRW(TweakBar, "Disco", TW_TYPE_BOOLCPP, &g_disco_mode, " group='Toggle ON/OFF' ");
// initialise rendering states
init(window);
// the rendering loop
while (!glfwWindowShouldClose(window))
{
g_camera.update(window); // update camera
if (g_wireFrame)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
update_scene(); // update the scene
render_scene(); // render the scene
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
TwDraw(); // draw tweak bar(s)
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
}
...
}
你必须测试是否达到上限或下限然后你必须改变方向
您的代码应该看起来像这样:
if ( movement_increase )
{
// if less than ceiling keep increasing
movement_increase = g_lightProperties.direction[0] < ceiling;
}
else
{
// if less or equal floor change to increasing
movement_increase = g_lightProperties.direction[0] <= floor;
}
g_lightProperties.direction[0] += movement_increase ? increment : -increment;
if ( color_increase )
color_increase = g_spotlight_ambient[0] < 1.0;
else
color_increase = g_spotlight_ambient[0] <= 0.0;
g_spotlight_ambient[0] += color_increase ? increment : -increment;
另外变量movement_increase
和color_increase
是局部变量,所以会每隔一段时间连续初始化。您要么使用全局变量,要么使用 delcare 它们 static
:
static bool movement_increase = true;
static bool color_increase = true;
我的程序是一个房间,中间有一个光源(球体)。
我想制作一个 "disco" 模式,使球体沿 x 轴左右移动。并且同时在红色和蓝色之间交替它的颜色。
这是我启用该模式的代码部分。 g_disco_mode
是选择模式后为真的变量。
static void update_scene()
{
...
// Disco mode
if (g_disco_mode)
{
bool movement_increase = true;
bool color_increase = true;
float floor = -0.1f;
float ceiling = 1.0f;
float increment = 0.01f;
// Movement of spotlight
if (movement_increase == true && g_lightProperties.direction[0] <= ceiling)
{
g_lightProperties.direction[0] += increment;
if (g_lightProperties.direction[0] >= ceiling) { movement_increase = false; }
}
if (movement_increase == false && g_lightProperties.direction[0] >= floor)
{
g_lightProperties.direction[0] -= increment;
if (g_lightProperties.direction[0] <= floor) { movement_increase = true; }
}
// Changing of color
g_spotlight_ambient[0] += 0.01f;
if (color_increase == true && g_spotlight_ambient[0] <= ceiling)
{
g_spotlight_ambient[0] += increment;
if (g_spotlight_ambient[0] >= ceiling) { color_increase = false; }
}
if (color_increase == false && g_spotlight_ambient[0] >= floor)
{
g_spotlight_ambient[0] -= increment;
if (g_spotlight_ambient[0] <= floor) { color_increase = true; }
}
}
}
我编写了这部分代码,使球体向右移动直到碰到 ceiling
,然后向左移动直到碰到 floor
。这是通过递增和递减 g_lightProperties.direction
来完成的。
颜色的变化也以类似的方式工作。然而,当我 运行 我的程序时,球体向右移动直到它碰到 ceiling
然后停止。它不会向左移动。对于颜色,它只是不断变红,不会变回蓝色。为什么会这样?
我的程序
// Values for spotlight
glm::vec3 g_spotlight_ambient(0.2f, 0.2f, 0.2f);
glm::vec3 g_spotlight_diffuse(0.0f, 0.5f, 1.0f);
glm::vec3 g_spotlight_specular(0.0f, 0.5f, 1.0f);
bool g_switchOn = true; // toggle the light on/off
bool g_disco_mode = false; // makes the lights move around and change color
static void init(GLFWwindow* window)
{
...
// initialise light and material properties
g_lightProperties.position = glm::vec4(0.0f, 2.0f, 0.0f, 1.0f);
g_lightProperties.ambient = glm::vec4(g_spotlight_ambient[0], g_spotlight_ambient[1], g_spotlight_ambient[2], 1.0f);
g_lightProperties.diffuse = glm::vec4(g_spotlight_diffuse[0], g_spotlight_diffuse[1], g_spotlight_diffuse[2], 1.0f);
g_lightProperties.specular = glm::vec4(g_spotlight_specular[0], g_spotlight_specular[1], g_spotlight_specular[2], 1.0f);
g_lightProperties.shininess = 10.0f;
g_lightProperties.attenuation = glm::vec3(1.0f, 0.0f, 0.0f);
g_lightProperties.cutoffAngle = 100.0f;
g_lightProperties.direction = glm::vec3(0.0f, -1.0f, 0.0f);
...
}
// function used to update the scene
static void update_scene()
{
static float rotateAngle = 0.0f;
static float cutOffAngle = g_lightProperties.cutoffAngle;
rotateAngle -= 1.0f;
// update model matrix
g_modelMatrix_mesh[0] = glm::rotate(glm::radians(rotateAngle), glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(-0.4f, 0.1f, 0.0f)) * glm::scale(glm::vec3(0.3f, 0.3f, 0.3f));
g_modelMatrix_mesh[1] = glm::rotate(glm::radians(rotateAngle), glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(0.4f, 0.3f, 0.0f)) * glm::scale(glm::vec3(0.2f, 0.2f, 0.2f));
g_modelMatrix_mesh[2] = glm::translate(g_lightProperties.direction)
* glm::translate(glm::vec3(0.0f, 2.0f, 0.0f)) * glm::scale(glm::vec3(0.2f, 0.2f, 0.2f));
// update spotlight
g_lightProperties.ambient = glm::vec4(g_spotlight_ambient[0], g_spotlight_ambient[1], g_spotlight_ambient[2], 1.0f);
g_lightProperties.diffuse = glm::vec4(g_spotlight_diffuse[0], g_spotlight_diffuse[1], g_spotlight_diffuse[2], 1.0f);
g_lightProperties.specular = glm::vec4(g_spotlight_specular[0], g_spotlight_specular[1], g_spotlight_specular[2], 1.0f);
// Disco mode
if (g_disco_mode)
{
bool movement_increase = true;
bool color_increase = true;
float floor = -0.1f;
float ceiling = 1.0f;
float increment = 0.01f;
// Movement of spotlight
if (movement_increase == true && g_lightProperties.direction[0] <= ceiling)
{
g_lightProperties.direction[0] += increment;
if (g_lightProperties.direction[0] >= ceiling) { movement_increase = false; }
}
if (movement_increase == false && g_lightProperties.direction[0] >= floor)
{
g_lightProperties.direction[0] -= increment;
if (g_lightProperties.direction[0] <= floor) { movement_increase = true; }
}
// Changing of color
g_spotlight_ambient[0] += 0.01f;
if (color_increase == true && g_spotlight_ambient[0] <= ceiling)
{
g_spotlight_ambient[0] += increment;
if (g_spotlight_ambient[0] >= ceiling) { color_increase = false; }
}
if (color_increase == false && g_spotlight_ambient[0] >= floor)
{
g_spotlight_ambient[0] -= increment;
if (g_spotlight_ambient[0] <= floor) { color_increase = true; }
}
}
}
// function used to render the scene
static void render_scene()
{
glBindVertexArray(g_VAO[0]); // make VAO active
// Material Properties - Planes
glUniform4fv(g_materialAmbientIndex, 1, &g_materialProperties.ambient[0]);
glUniform4fv(g_materialDiffuseIndex, 1, &g_materialProperties.diffuse[0]);
glUniform4fv(g_materialSpecularIndex, 1, &g_materialProperties.specular[0]);
glUniform4fv(g_lightPositionIndex, 1, &g_lightProperties.position[0]);
glUniform4fv(g_lightAmbientIndex, 1, &g_lightProperties.ambient[0]);
glUniform4fv(g_lightDiffuseIndex, 1, &g_lightProperties.diffuse[0]);
glUniform4fv(g_lightSpecularIndex, 1, &g_lightProperties.specular[0]);
glUniform1fv(g_lightShininessIndex, 1, &g_lightProperties.shininess);
glUniform3fv(g_lightAttenuationIndex, 1, &g_lightProperties.attenuation[0]);
glUniform1fv(g_lightCutoffAngleIndex, 1, &g_lightProperties.cutoffAngle);
glUniform3fv(g_lightDirectionIndex, 1, &g_lightProperties.direction[0]);
...
}
int main(void)
{
TwBar *TweakBar; // pointer to a tweak bar
...
// initialise AntTweakBar
TwInit(TW_OPENGL_CORE, NULL);
// give tweak bar the size of graphics window
TwWindowSize(g_windowWidth, g_windowHeight);
TwDefine(" TW_HELP visible=false "); // disable help menu
TwDefine(" GLOBAL fontsize=3 "); // set large font size
// create a tweak bar
TweakBar = TwNewBar("Main");
TwDefine(" Main label='Controls' refresh=0.02 text=light size='220 600' ");
// create display entries
TwAddVarRW(TweakBar, "Wireframe", TW_TYPE_BOOLCPP, &g_wireFrame, " group='Display' ");
// display a separator
TwAddSeparator(TweakBar, NULL, NULL);
// create spotlight entries
TwAddVarRW(TweakBar, "Cutoff", TW_TYPE_FLOAT, &g_lightProperties.cutoffAngle, " group='Spotlight' min=-180.0 max=180.0 step=1.0 ");
TwAddVarRW(TweakBar, "Direction: x", TW_TYPE_FLOAT, &g_lightProperties.direction[0], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
TwAddVarRW(TweakBar, "Direction: y", TW_TYPE_FLOAT, &g_lightProperties.direction[1], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
TwAddVarRW(TweakBar, "Direction: z", TW_TYPE_FLOAT, &g_lightProperties.direction[2], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
// create transformation entries
TwAddVarRW(TweakBar, "A Red", TW_TYPE_FLOAT, &g_spotlight_ambient[0], " group='Ambient' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "A Green", TW_TYPE_FLOAT, &g_spotlight_ambient[1], " group='Ambient' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "A Blue", TW_TYPE_FLOAT, &g_spotlight_ambient[2], " group='Ambient' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "D Red", TW_TYPE_FLOAT, &g_spotlight_diffuse[0], " group='Diffuse' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "D Green", TW_TYPE_FLOAT, &g_spotlight_diffuse[1], " group='Diffuse' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "D Blue", TW_TYPE_FLOAT, &g_spotlight_diffuse[2], " group='Diffuse' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "S Red", TW_TYPE_FLOAT, &g_spotlight_specular[0], " group='Specular' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "S Green", TW_TYPE_FLOAT, &g_spotlight_specular[1], " group='Specular' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "S Blue", TW_TYPE_FLOAT, &g_spotlight_specular[2], " group='Specular' min=-1.0 max=1.0 step=0.01");
TwAddVarRW(TweakBar, "Light", TW_TYPE_BOOLCPP, &g_switchOn, " group='Toggle ON/OFF' ");
TwAddVarRW(TweakBar, "Disco", TW_TYPE_BOOLCPP, &g_disco_mode, " group='Toggle ON/OFF' ");
// initialise rendering states
init(window);
// the rendering loop
while (!glfwWindowShouldClose(window))
{
g_camera.update(window); // update camera
if (g_wireFrame)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
update_scene(); // update the scene
render_scene(); // render the scene
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
TwDraw(); // draw tweak bar(s)
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
}
...
}
你必须测试是否达到上限或下限然后你必须改变方向
您的代码应该看起来像这样:
if ( movement_increase )
{
// if less than ceiling keep increasing
movement_increase = g_lightProperties.direction[0] < ceiling;
}
else
{
// if less or equal floor change to increasing
movement_increase = g_lightProperties.direction[0] <= floor;
}
g_lightProperties.direction[0] += movement_increase ? increment : -increment;
if ( color_increase )
color_increase = g_spotlight_ambient[0] < 1.0;
else
color_increase = g_spotlight_ambient[0] <= 0.0;
g_spotlight_ambient[0] += color_increase ? increment : -increment;
另外变量movement_increase
和color_increase
是局部变量,所以会每隔一段时间连续初始化。您要么使用全局变量,要么使用 delcare 它们 static
:
static bool movement_increase = true;
static bool color_increase = true;