Perhatikan bahwa hal-hal seperti pemetaan tekstur dan pencahayaan masih akan diterapkan ke garis rangka gambar jika diaktifkan, yang bisa terlihat aneh.
membuat dua panggilan itu mubazir. gunakan GL_FRONT_AND_BACK
shoosh
6
Sebagai tambahan untuk komentar @ shoosh, Buku Merah menyatakan bahwa GL_FRONT dan GL_BACK telah ditinggalkan dan dihapus dari OpenGL 3.1 dan lebih tinggi. Sekarang, Anda masih dapat menggunakannya melalui ekstensi kompatibilitas, tetapi jika Anda memiliki pilihan antara kompatibel maju dan kompatibel mundur, saya akan merekomendasikan pergi untuk yang pertama.
Fouric
1
Tautan dalam jawaban ini mengembalikan 404.
Ondrej Slinták
1
@ OndrejSlinták Sudah diperbaiki sekarang.
MaxiMouse
24
Dengan asumsi konteks yang kompatibel maju dalam OpenGL 3 dan yang lebih tinggi, Anda dapat menggunakan glPolygonModeseperti yang disebutkan sebelumnya, tetapi perhatikan bahwa garis dengan ketebalan lebih dari 1px sekarang tidak digunakan lagi. Jadi, sementara Anda bisa menggambar segitiga sebagai bingkai kawat, mereka harus sangat tipis. Di OpenGL ES, Anda dapat menggunakan GL_LINESdengan batasan yang sama.
Dalam OpenGL adalah mungkin untuk menggunakan geometri shader untuk mengambil segitiga masuk, membongkar mereka dan mengirimkannya untuk rasterisasi sebagai paha depan (pasangan segitiga benar-benar) meniru garis tebal. Cukup sederhana, sungguh, kecuali bahwa shader geometri terkenal karena penskalaan kinerja yang buruk.
Yang dapat Anda lakukan sebagai gantinya, dan apa yang juga akan berfungsi di OpenGL ES adalah menggunakan fragmen shader. Pikirkan menerapkan tekstur segitiga kawat-bingkai ke segitiga. Kecuali bahwa tidak diperlukan tekstur, itu dapat dihasilkan secara prosedural. Tapi cukup bicara, mari kita kode. Shader fragmen:
in vec3 v_barycentric;// barycentric coordinate inside the triangle
uniform float f_thickness;// thickness of the rendered linesvoid main(){float f_closest_edge = min(v_barycentric.x,
min(v_barycentric.y, v_barycentric.z));// see to which edge this pixel is the closestfloat f_width = fwidth(f_closest_edge);// calculate derivative (divide f_thickness by this to have the line width constant in screen-space)float f_alpha = smoothstep(f_thickness, f_thickness + f_width, f_closest_edge);// calculate alpha
gl_FragColor = vec4(vec3(.0), f_alpha);}
Dan vertex shader:
in vec4 v_pos;// position of the vertices
in vec3 v_bc;// barycentric coordinate inside the triangle
out vec3 v_barycentric;// barycentric coordinate inside the triangle
uniform mat4 t_mvp;// modeview-projection matrixvoid main(){
gl_Position = t_mvp * v_pos;
v_barycentric = v_bc;// just pass it on}
Di sini, koordinat barycentric sederhana (1, 0, 0), (0, 1, 0)dan (0, 0, 1)untuk tiga simpul segitiga (urutannya tidak terlalu penting, yang membuat pengemasan menjadi strip segitiga berpotensi lebih mudah).
Kerugian yang jelas dari pendekatan ini adalah ia akan memakan beberapa koordinat tekstur dan Anda perlu memodifikasi array vertex Anda. Bisa diselesaikan dengan shader geometri yang sangat sederhana tapi saya masih curiga ini akan lebih lambat daripada hanya memberi makan GPU dengan lebih banyak data.
Saya pikir ini tampak menjanjikan, namun ini tampaknya tidak berfungsi dalam kapasitas apa pun dengan OpenGL 3.2 (non-ES). Meskipun mungkin saya mengacaukan sesuatu, saya bermain-main dengan ini cukup lama dan tidak yakin bagaimana ini bahkan dimaksudkan untuk digunakan. Setiap informasi lebih lanjut tentang apa yang ingin Anda render dengan shader ini akan sangat membantu; Saya tidak melihat bagaimana selain pengisian akan menghasilkan sesuatu yang bermanfaat, tetapi itu bahkan tidak berhasil mengingat bahwa nilai alpha dari gl_FragColor tampaknya sepenuhnya diabaikan di OpenGL 3.2 ...
Masalah yang saya alami ketika mencoba menggunakan implementasi yang Anda sarankan adalah, saya pikir, bahwa shader tidak akan pernah menggambar di luar objek yang akan diuraikan. Oleh karena itu ini akan menggambar garis besar objek yang diuraikan? Dengan kata lain, garis besar akan murni terkandung dalam objek asli yang akan ditarik?
user1167662
1
@ BrunoLevy Anda bisa mendapatkan tambahan yang terkoordinasi di webGL, bukan? Jika Anda beruntung, Anda mungkin bisa mendapatkan koordinat tersebut dari texcoords jika Anda memiliki model yang sangat sederhana tetapi Anda hanya perlu menambahkan koordinat baru. Akan terlalu bagus jika berhasil tanpanya :). Yang Anda butuhkan adalah untuk melewatkan skalar tunggal per titik (dan kemudian memperluasnya menjadi 3-vektor dalam vertex shader).
babi
2
Ah, sekarang saya mengerti ... f_width () adalah teman saya, dalam hal ini. Terima kasih
Neil Gatenby
5
Jika Anda menggunakan pipa tetap (OpenGL <3.3) atau profil kompatibilitas yang dapat Anda gunakan
//Turn on wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//Draw the scene with polygons as lines (wireframe)
renderScene();
//Turn off wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
Dalam hal ini Anda dapat mengubah lebar garis dengan memanggil glLineWidth
Kalau tidak, Anda perlu mengubah mode poligon di dalam metode menggambar Anda (glDrawElements, glDrawArrays, dll) dan Anda mungkin berakhir dengan beberapa hasil kasar karena data vertex Anda adalah untuk segitiga dan Anda menghasilkan garis. Untuk hasil terbaik, pertimbangkan untuk menggunakan Geometri shader atau membuat data baru untuk kerangka gambar.
tidak jika itu adalah sekelompok GL_TRIANGLES: Anda akan mendapatkan garis di antara mereka. Di OpenGL 1.x atau legacy Anda menggunakan glPolygonMode. Di OpenGL terbaru Anda bermain dengan shader geometri.
Fabrice NEYRET
Ini adalah cara kuno dalam melakukan hal-hal yang perlu ditinggalkan.
Benny Mackney
2
Di Modern OpenGL (OpenGL 3.2 dan lebih tinggi), Anda bisa menggunakan Geometry Shader untuk ini:
#version 330
layout (triangles) in;
layout (line_strip /*for lines, use "points" for points*/, max_vertices=3) out;
in vec2 texcoords_pass[]; //Texcoords from Vertex Shader
in vec3 normals_pass[]; //Normals from Vertex Shader
out vec3 normals; //Normals for Fragment Shader
out vec2 texcoords; //Texcoords for Fragment Shader
void main(void)
{
int i;
for (i = 0; i < gl_in.length(); i++)
{
texcoords=texcoords_pass[i]; //Pass through
normals=normals_pass[i]; //Pass through
gl_Position = gl_in[i].gl_Position; //Pass through
EmitVertex();
}
EndPrimitive();
}
Pemberitahuan:
untuk poin, ubah layout (line_strip, max_vertices=3) out;kelayout (points, max_vertices=3) out;
Cara yang baik dan sederhana untuk menggambar garis anti-alias pada target render non-alias adalah menggambar persegi empat dengan lebar 4 piksel dengan tekstur 1x4, dengan nilai saluran alfa dari {0., 1., 1., 0.} , dan gunakan pemfilteran linear dengan memetakan mip. Ini akan membuat garis-garis tebal 2 piksel, tetapi Anda dapat mengubah tekstur untuk ketebalan yang berbeda. Ini lebih cepat dan lebih mudah daripada perhitungan barymetric.
gunakan fungsi ini: void glPolygonMode (wajah GLenum, mode GLenum);
wajah: Menentukan poligon yang berlaku mode. bisa menjadi GL_FRONT untuk sisi depan poligon dan GL_BACK untuk punggungnya dan GL_FRONT_AND_BACK untuk keduanya.
mode: Tiga mode didefinisikan dan dapat ditentukan dalam mode:
GL_POINT: Simpul poligon yang ditandai sebagai awal dari batas batas digambarkan sebagai titik.
GL_LINE: Tepi batas poligon diambil sebagai segmen garis. (target Anda)
GL_FILL: Bagian dalam poligon terisi.
PS: glPolygonMode mengontrol interpretasi poligon untuk rasterisasi dalam pipa grafis.
Jawaban:
untuk menghidupkan,
untuk kembali normal.
Perhatikan bahwa hal-hal seperti pemetaan tekstur dan pencahayaan masih akan diterapkan ke garis rangka gambar jika diaktifkan, yang bisa terlihat aneh.
sumber
Dari http://cone3d.gamedev.net/cgi-bin/index.pl?page=tutorials/ogladv/tut5
sumber
Dengan asumsi konteks yang kompatibel maju dalam OpenGL 3 dan yang lebih tinggi, Anda dapat menggunakan
glPolygonMode
seperti yang disebutkan sebelumnya, tetapi perhatikan bahwa garis dengan ketebalan lebih dari 1px sekarang tidak digunakan lagi. Jadi, sementara Anda bisa menggambar segitiga sebagai bingkai kawat, mereka harus sangat tipis. Di OpenGL ES, Anda dapat menggunakanGL_LINES
dengan batasan yang sama.Dalam OpenGL adalah mungkin untuk menggunakan geometri shader untuk mengambil segitiga masuk, membongkar mereka dan mengirimkannya untuk rasterisasi sebagai paha depan (pasangan segitiga benar-benar) meniru garis tebal. Cukup sederhana, sungguh, kecuali bahwa shader geometri terkenal karena penskalaan kinerja yang buruk.
Yang dapat Anda lakukan sebagai gantinya, dan apa yang juga akan berfungsi di OpenGL ES adalah menggunakan fragmen shader. Pikirkan menerapkan tekstur segitiga kawat-bingkai ke segitiga. Kecuali bahwa tidak diperlukan tekstur, itu dapat dihasilkan secara prosedural. Tapi cukup bicara, mari kita kode. Shader fragmen:
Dan vertex shader:
Di sini, koordinat barycentric sederhana
(1, 0, 0)
,(0, 1, 0)
dan(0, 0, 1)
untuk tiga simpul segitiga (urutannya tidak terlalu penting, yang membuat pengemasan menjadi strip segitiga berpotensi lebih mudah).Kerugian yang jelas dari pendekatan ini adalah ia akan memakan beberapa koordinat tekstur dan Anda perlu memodifikasi array vertex Anda. Bisa diselesaikan dengan shader geometri yang sangat sederhana tapi saya masih curiga ini akan lebih lambat daripada hanya memberi makan GPU dengan lebih banyak data.
sumber
Jika Anda menggunakan pipa tetap (OpenGL <3.3) atau profil kompatibilitas yang dapat Anda gunakan
Dalam hal ini Anda dapat mengubah lebar garis dengan memanggil glLineWidth
Kalau tidak, Anda perlu mengubah mode poligon di dalam metode menggambar Anda (glDrawElements, glDrawArrays, dll) dan Anda mungkin berakhir dengan beberapa hasil kasar karena data vertex Anda adalah untuk segitiga dan Anda menghasilkan garis. Untuk hasil terbaik, pertimbangkan untuk menggunakan Geometri shader atau membuat data baru untuk kerangka gambar.
sumber
Cara termudah adalah menggambar primitif sebagai
GL_LINE_STRIP
.sumber
Di Modern OpenGL (OpenGL 3.2 dan lebih tinggi), Anda bisa menggunakan Geometry Shader untuk ini:
Pemberitahuan:
layout (line_strip, max_vertices=3) out;
kelayout (points, max_vertices=3) out;
sumber
Anda dapat menggunakan pustaka glut seperti ini:
untuk bola:
untuk Silinder:
untuk Cube:
sumber
Cara yang baik dan sederhana untuk menggambar garis anti-alias pada target render non-alias adalah menggambar persegi empat dengan lebar 4 piksel dengan tekstur 1x4, dengan nilai saluran alfa dari {0., 1., 1., 0.} , dan gunakan pemfilteran linear dengan memetakan mip. Ini akan membuat garis-garis tebal 2 piksel, tetapi Anda dapat mengubah tekstur untuk ketebalan yang berbeda. Ini lebih cepat dan lebih mudah daripada perhitungan barymetric.
sumber
gunakan fungsi ini: void glPolygonMode (wajah GLenum, mode GLenum);
wajah: Menentukan poligon yang berlaku mode. bisa menjadi GL_FRONT untuk sisi depan poligon dan GL_BACK untuk punggungnya dan GL_FRONT_AND_BACK untuk keduanya.
mode: Tiga mode didefinisikan dan dapat ditentukan dalam mode:
GL_POINT: Simpul poligon yang ditandai sebagai awal dari batas batas digambarkan sebagai titik.
GL_LINE: Tepi batas poligon diambil sebagai segmen garis. (target Anda)
GL_FILL: Bagian dalam poligon terisi.
PS: glPolygonMode mengontrol interpretasi poligon untuk rasterisasi dalam pipa grafis.
untuk informasi lebih lanjut lihat halaman referensi OpenGL di grup khronos: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonMode.xhtml
sumber
Jika OpenGL ES 2.0 yang Anda hadapi, Anda dapat memilih salah satu dari konstanta mode undian
GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,
untuk menggambar garis,GL_POINTS
(jika Anda hanya perlu menggambar simpul), atauGL_TRIANGLE_STRIP
,,GL_TRIANGLE_FAN
danGL_TRIANGLES
menggambar segitiga yang diisisebagai argumen pertama untuk Anda
atau
glDrawArrays(GLenum mode, GLint first, GLsizei count)
panggilan.sumber