- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图让一个形状因光源而具有一些阴影,但我希望所有形状都是一种颜色。
我的问题是,无论我多么努力,我似乎都无法在单一颜色模型上获得任何阴影。我已将我的模型简化为单个三角形以使此示例更清晰:
#include <GL/glut.h>
#include <math.h>
#include <iostream>
#include<map>
#include<vector>
using namespace std;
/* Verticies for simplified demo */
float vertices[][3] = {
{0.1, 0.1, 0.1},
{0.2, 0.8, 0.3},
{0.3, 0.5, 0.5},
{0.8, 0.2, 0.1},
};
const int VERTICES_SIZE = 4;
/* Polygons for simplified demo */
int polygon[][3] = {
{0, 1, 3},
{0, 2, 1},
{0, 3, 2},
{1, 2, 3},
};
const int POLYGON_SIZE = 4;
/* Average point for looking at */
float av_point[3];
/*
* Holds the normal for each vertex calculated by averaging the
* planar normals that each vertex is connected to.
* It holds {index_of_vertex_in_vertices : normal}
*/
map<int, float*> vertex_normals;
/*
* Calculates average point in list of vertices
* Stores in result
*/
void averagePoint(float vertices[][3], int length, float result[3]) {
for(int i = 0; i < length; i++) {
result[0] += vertices[i][0];
result[1] += vertices[i][1];
result[2] += vertices[i][2];
}
result[0] /= length;
result[1] /= length;
result[2] /= length;
}
/*
* Performs inplace normalisation of vector v
*/
void normalise(float v[3]) {
GLfloat length = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] /= length;
v[1] /= length;
v[2] /= length;
}
/*
* Performs cross product of vectors u and v and stores
* result in result
* Normalises result.
*/
void crossProduct(float u[], float v[], float result[]) {
result[0] = u[1] * v[2] - u[2] * v[1];
result[1] = u[2] * v[0] - u[0] * v[2];
result[2] = u[0] * v[1] - u[1] * v[0];
}
/*
* Calculates normal for plane
*/
void calculate_normal(int polygon[3], float vertices[][3], float normal[3]) {
GLfloat u[3], v[3];
for (int i = 0; i < 3; i++) {
u[i] = vertices[polygon[0]][i] - vertices[polygon[1]][i];
v[i] = vertices[polygon[2]][i] - vertices[polygon[1]][i];
}
crossProduct(u, v, normal);
normalise(normal);
}
/*
* Populates vertex_normal with it's averaged face normal
*/
void calculate_vertex_normals (map<int, float*> &vertex_normal){
map<int, vector<int> > vertex_to_faces;
map<int, float*> faces_to_normal;
// Loop over faces
for (int i = 0; i < POLYGON_SIZE; i++) {
float* normal = new float[3];
calculate_normal(polygon[i], vertices, normal);
for (int j = 0; j < 3; j++) {
vertex_to_faces[polygon[i][j]].push_back(i);
}
faces_to_normal[i] = normal;
}
vertex_normal.clear();
// Loop over vertices
for (int v = 0; v < VERTICES_SIZE; v++) {
vector<int> faces = vertex_to_faces[v];
int faces_count = 0;
float* normal = new float[3];
for (vector<int>::iterator it = faces.begin(); it != faces.end(); ++it){
normal[0] += faces_to_normal[*it][0];
normal[1] += faces_to_normal[*it][1];
normal[2] += faces_to_normal[*it][2];
faces_count++;
}
normal[0] /= faces_count;
normal[1] /= faces_count;
normal[2] /= faces_count;
vertex_normal[v] = normal;
}
// Delete normal declared in first loop
for (int i = 0; i < POLYGON_SIZE; i++) {
delete faces_to_normal[i];
}
}
/*
* Draws polygons in polygon array.
*/
void draw_polygon() {
for(int i = 0; i < POLYGON_SIZE; i++) {
glBegin(GL_POLYGON);
for(int j = 0; j < 3; j++) {
glNormal3fv(vertex_normals[polygon[i][j]]);
glVertex3fv(vertices[polygon[i][j]]);
}
glEnd();
}
}
/*
* Sets up lighting and material properties
*/
void init()
{
// Calculate average point for looking at
averagePoint(vertices, VERTICES_SIZE, av_point);
// Calculate vertices average normals
calculate_vertex_normals(vertex_normals);
glClearColor (0.0, 0.0, 0.0, 0.0);
cout << "init" << endl;
// Intialise and set lighting parameters
GLfloat light_pos[] = {1.0, 1.0, 1.0, 0.0};
GLfloat light_ka[] = {0.2, 0.2, 0.2, 1.0};
GLfloat light_kd[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_ks[] = {1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ka);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_kd);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_ks);
// Initialise and set material parameters
GLfloat material_ka[] = {1.0, 1.0, 1.0, 1.0};
GLfloat material_kd[] = {0.43, 0.47, 0.54, 1.0};
GLfloat material_ks[] = {0.33, 0.33, 0.52, 1.0};
GLfloat material_ke[] = {0.0, 0.0, 0.0, 0.0};
GLfloat material_se[] = {10.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ka);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_kd);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_ks);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, material_ke);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, material_se);
// Smooth shading
glShadeModel(GL_SMOOTH);
// Enable lighting
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
// Enable Z-buffering
glEnable(GL_DEPTH_TEST);
}
/*
* Free's resources
*/
void destroy() {
for (int i = 0; i < VERTICES_SIZE; i++) {
delete vertex_normals[i];
}
}
/*
* Display simple polygon
*/
void display (){
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_polygon();
glutSwapBuffers();
}
/*
* Sets up camera perspective and view point
* Looks at average point in model.
*/
void reshape (int w, int h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70, 1.0, 0.1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 1, av_point[0], av_point[1], av_point[2], 0, 0.5, 0);
}
int main (int argc, char **argv)
{
// Initialize graphics window
glutInit(&argc, argv);
glutInitWindowSize(256, 256);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);
// Initialize OpenGL
init();
glutCreateWindow("Rendering");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop ();
destroy();
return 1;
}
我是 OpenGL 的新手,所以我希望它很简单。由于我记得设置我的法线,所以我不确定还有什么问题。
最终目标是为我的类(class)作业渲染一张带有 Gouraud 阴影(然后是纹理)的脸,但是我们几乎只能自己弄清楚 OpenGL(1.4 - 类(class)要求),而且我们不允许使用着色器。我正在尝试创建类似于这张图片的东西(取自谷歌):
用我的三角形。
最佳答案
shading due to a light source but I'd like the shape to all be one colour.
这两个要求不是相互排斥的吗?你想要的结果到底是什么。你能画出你想象的图吗?在实现方面,使用着色器比处理大量 OpenGL 状态机开关要容易得多。
无论如何,这是我修改后的 OP 代码版本,它绘制了一个受 Gourad 照明影响的三角形。这段代码编译并绘制了一个带有镜面反射提示的三角形。
让我们回顾一下我所做的。首先是三角形的原始设置。这里没有什么特别的也没有任何改变(除了一些包含) (编辑)第二次看我做了改变。 std::map 的使用完全没有说明。我们知道顶点的数量并且可以预分配法线的内存。
#include <GL/glut.h>
#include <math.h>
// for memcpy
#include <string.h>
#include <map>
#include <vector>
#include <iostream>
using namespace::std;
/* Verticies for simplified demo */
const int VERTICES_SIZE = 4;
float vertices[VERTICES_SIZE][3] = {
{0.1, 0.1, 0.1},
{0.2, 0.8, 0.3},
{0.3, 0.5, 0.5},
{0.8, 0.2, 0.1},
};
// this is now a plain array
float vertex_normals[VERTICES_SIZE][3];
/* Polygons for simplified demo */
const int POLYGON_SIZE = 4;
int polygon[POLYGON_SIZE][3] = {
{0, 1, 3},
{0, 2, 1},
{0, 3, 2},
{1, 2, 3},
};
/* Average point for looking at */
float av_point[3];
/*
* Calculates average point in list of vertices
* Stores in result
*/
void averagePoint(float vertices[][3], int length, float result[3]) {
for(int i = 0; i < length; i++) {
result[0] += vertices[i][0];
result[1] += vertices[i][1];
result[2] += vertices[i][2];
}
result[0] /= length;
result[1] /= length;
result[2] /= length;
}
/*
* Performs inplace normalisation of vector v
*/
void normalise(float v[3]) {
GLfloat length = sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] /= length;
v[1] /= length;
v[2] /= length;
}
/*
* Performs cross product of vectors u and v and stores
* result in result
* Normalises result.
*/
void crossProduct(float u[], float v[], float result[]) {
result[0] = u[1] * v[2] - u[2] * v[1];
result[1] = u[2] * v[0] - u[0] * v[2];
result[2] = u[0] * v[1] - u[1] * v[0];
}
/*
* Calculates normal for plane
*/
void calculate_normal(int polygon[3], float vertices[][3], float normal[3]) {
GLfloat u[3], v[3];
for (int i = 0; i < 3; i++) {
u[i] = vertices[polygon[0]][i] - vertices[polygon[1]][i];
v[i] = vertices[polygon[2]][i] - vertices[polygon[1]][i];
}
crossProduct(u, v, normal);
normalise(normal);
}
编辑:我的下一个更改在这里。看评论
/*
* Populates normals with it's averaged face normal
*
* Passing the normal output buffer as a parameter was a bit
* pointless, as this procedure accesses global variables anyway.
* Either pass everything as parameters or noting at all,
* be consequent. And doing it mixed is pure evil.
*/
void calculate_vertex_normals()
{
// We love RAII, no need for new and delete!
vector< vector<int> > vertex_to_faces(POLYGON_SIZE);
vector< vector<float> > faces_to_normal(POLYGON_SIZE);
// Loop over faces
for (int i = 0; i < POLYGON_SIZE; i++) {
vector<float> normal(3);
calculate_normal(polygon[i], vertices, &normal[0]);
for (int j = 0; j < 3; j++) {
vertex_to_faces[polygon[i][j]].push_back(i);
}
faces_to_normal[i] = normal;
}
// Loop over vertices
for (int v = 0; v < VERTICES_SIZE; v++) {
// avoid a copy here by using a reference
vector<int> &faces = vertex_to_faces[v];
int faces_count = 0;
float normal[3];
for (vector<int>::iterator it = faces.begin(); it != faces.end(); ++it){
normal[0] += faces_to_normal[*it][0];
normal[1] += faces_to_normal[*it][1];
normal[2] += faces_to_normal[*it][2];
faces_count++;
}
// dividing a vector obtained by a number of unit length vectors
// summed by the number of unit vectors summed does not normalize
// it. You need to normalize it properly!
normalise(normal);
// memcpy is really be best choice here
memcpy(vertex_normals[v], normal, sizeof(normal));
}
}
draw_polygon 是这个函数的一个相当不愉快的名字。它绘制了一个三角网格。 *编辑:它也可以通过使用顶点数组(自 1994 年以来可用的 OpenGL-1.1)来编写得更好。
/*
* Draws polygons in polygon array.
*/
void draw_polygon() {
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &vertices[0][0]);
glNormalPointer(GL_FLOAT, 0, &vertex_normals[0][0]);
glDrawElements(GL_TRIANGLES, POLYGON_SIZE*3, GL_UNSIGNED_INT, polygon);
}
这里变得有趣了。一个常见的误解是,人们认为 OpenGL 已“初始化”。事实并非如此。你初始化的是数据。在你的情况下你的几何数据
/*
* Sets up lighting and material properties
*/
void init_geometry()
{
// Calculate average point for looking at
averagePoint(vertices, VERTICES_SIZE, av_point);
// Calculate vertices average normals
calculate_vertex_normals(vertex_normals);
}
棘手的部分来了:OpenGL 固定功能照明是一种状态,与其他一切一样。当您调用 glLightfv 时,它将根据调用时的状态设置内部参数。调用时位置由模型 View 转换。但是如果没有设置正确的模型 View ,您将无法设置照明。因此我把它放在它自己的函数中,我们在绘图函数中设置模型 View 后立即调用它。
void setup_illumination()
{
// Intialise and set lighting parameters
GLfloat light_pos[] = {1.0, 1.0, 1.0, 0.0};
GLfloat light_ka[] = {0.2, 0.2, 0.2, 1.0};
GLfloat light_kd[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_ks[] = {1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ka);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_kd);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_ks);
// Initialise and set material parameters
GLfloat material_ka[] = {1.0, 1.0, 1.0, 1.0};
GLfloat material_kd[] = {0.43, 0.47, 0.54, 1.0};
GLfloat material_ks[] = {0.33, 0.33, 0.52, 1.0};
GLfloat material_ke[] = {0.0, 0.0, 0.0, 0.0};
GLfloat material_se[] = {10.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ka);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_kd);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_ks);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, material_ke);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, material_se);
// Smooth shading
glShadeModel(GL_SMOOTH);
// Enable lighting
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
}
对于绘图函数,有几处发生了变化。看代码中的注释
/*
* Display simple polygon
*/
void display (void)
{
// float window sizes are usefull for view volume calculations
//
// requesting the window dimensions for each drawing iteration
// is just two function calls. Compare this to the number of function
// calls a typical application will do for the actual rendering
// Trying to optimize away those two calls is a fruitless microoptimization
float const window_width = glutGet(GLUT_WINDOW_WIDTH);
float const window_height = glutGet(GLUT_WINDOW_HEIGHT);
float const window_aspect = window_width / window_height;
// glViewport operates independent of the projection --
// another reason to put it into the drawing code
glViewport(0, 0, window_width, window_height);
glClearDepth(1.);
glClearColor (0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// It's a often made mistake to setup projection in the window resize
// handler. Projection is a drawing state, hence should be set in
// the drawing code. Also in most programs you will have multiple
// projections mixed throughout rendering a single frame so there you
// actually **must** set projection in drawing code, otherwise it
// wouldn't work.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70, window_aspect, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, -3, av_point[0], av_point[1], av_point[2], 0, 1, 0);
// Fixed function pipeline light position setup calls operate on the current
// modelview matrix, so we must setup the illumination parameters with the
// modelview matrix at least after the view transformation (look-at) applied.
setup_illumination();
// Enable depth testing (z buffering would be enabled/disabled with glDepthMask)
glEnable(GL_DEPTH_TEST);
draw_polygon();
glutSwapBuffers();
}
int main (int argc, char **argv)
{
// Initialize graphics window
glutInit(&argc, argv);
glutInitWindowSize(256, 256);
glutInitDisplayMode (GLUT_DEPTH | GLUT_DOUBLE);
// we actually have to create a window
glutCreateWindow("illuination");
// Initialize geometry
init_geometry();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
关于c++ - 无法让 OpenGL 中的 Gouraud Shading 工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14796313/
我正在寻找一种方法来解析字符串以获取 int,然后偶然发现: NumberUtils.toInt("blah",99); 我将它输入到我的 IDE 中,它会自动为我导入它: import autova
我是一名 CS 学生,在我们的期末考试中,我们被告知要通过光线追踪在多个球体上构建反射。这几乎就是我们得到的指导,除了完成后的外观图片。所以我需要球体,它们是反射(使用光线追踪)映射到它们上的,并带有
我正在使用 maven 来配置由多个小型服务组成的应用程序。大多数用 java 开发的服务共享相同的 maven 配置,如在相同的构建生命周期中,一些共享资源(如 spring AMQP)。 所以我在
我正在尝试使用 HBaseTestingUtility 1.2 与 hbase-shaded-client & hbase-shaded-server .它向我抛出了以下异常。谁能告诉我如何避免这种情
当使用 m2eclipse 工具为为 Maven Shade Plugin 配置的项目在 eclipse 中运行 Maven 构建时,构建失败并显示以下错误消息: 无法执行目标 org.apache.
我直接从 apache maven 文档中复制了 maven shade 插件的配置 https://maven.apache.org/plugins/maven-shade-plugin/examp
我试图从 Spring Boot 运行 Hello World 示例。当我在模块上运行“mvn package”时,出现以下错误:- [ERROR] Failed to execute goal or
在尝试构建旧版本的 Apache CXF 2.2.2 时,我一直收到 maven-shade-plugin 使用的 XmlAppendingTransformer 产生的错误:无法连接以获取 ht
我正在尝试使用 maven-shade-plugin 来区分 Java 6 和 Java 7 Artifact 。我的理解来自this link就是原来的神器会被阴影的神器代替 [INFO] Repl
我正在尝试遮阳 aws-java-sdk为了按照提到的建议解决库冲突 here .但我看到 maven-shade-plugin ,资源文件(文本)中的条目没有得到更新。例如 request.hand
我正在寻找一个“神奇”的功能,它可以拍摄图像并返回副本,但将一组色调替换为另一组色调。 例如我有一张红色鱼的照片:它有各种灰度和黑色和白色,但本质上是各种深浅不一的红色。我想将它传递给这个“魔术”函数
开心一刻 有一天螃蟹出门,不小心撞倒了泥鳅泥鳅很生气地说:你是不是瞎啊!螃蟹说:不是啊,我是螃蟹 概述 maven-shade-plugin 官网已经介绍的很详细了,我给大家简单翻译一
开心一刻 有一天螃蟹出门,不小心撞倒了泥鳅泥鳅很生气地说:你是不是瞎啊!螃蟹说:不是啊,我是螃蟹 概述 maven-shade-plugin 官网已经介绍的很详细了,我给大家简单翻译一
我在我的项目中使用 commons-io 并想对其进行着色。我遇到了一个我似乎无法弄清楚的警告: [WARNING] commons-io-2.7.jar, murder-1.0-SNAPSHOT.j
我正在使用 shade 插件创建一个包含所有依赖项的 jar。在我的 pom.xml 中应用此配置相对简单: org.apache.maven.plugins maven-shade-plugin
上下文 我有一个包含多个模块的 IntelliJ 项目。我正在使用 maven-shade-plugin 来压缩依赖项,同时减少 jar 大小。项目结构如下; 顶级父级 (pom)(聚合 api 和
我有一个同时包含Java和Scala组件的maven项目,但是当我使用maven-shade-plugin时,它会同时为Java和Scala文件定位软件包名称,但是仅重命名Java文件中的软件包,Sc
到目前为止,我一直在使用 Maven 程序集插件为每个 Artifact 生成两个 JAR - 已编译的源代码和依赖项 - 原因很简单 - 通过网络仅部署已编译的源代码比部署一体化 JAR 快得多具有
我试图使用Maven Shade并包装ElasticSearch jar。 之所以这样做,是因为我的项目中Lucene版本之间存在冲突。 但是当我使用Shade时发现了问题。它不会更改META-INF
我正在使用 maven-shade-plugin 创建一个可执行 jar,其中包含项目的所有依赖项。有时,这些依赖项会带来自己的依赖项,这些依赖项会与其他库的依赖项发生冲突,并且 maven-shad
我是一名优秀的程序员,十分优秀!